Ruby on Rails ships with a lot of predefined validations for your models. Unfortunately there is no special email validation. Even Rails 2.0 does not ship it (check the ActiveRecord
changelog) yet. Because I needed it I had to write my own validates_email
method. I know there are a lot of plugins but non of them suits my needs. validates_email
does the following:
- checks if email is syntactically correct (using regex)
- checks if the host of the email is supported within the application. This is very important for me because I dont want ppl signing up with one-time emails from e.g. mailinator.com. (can be disabled)
For this we create a validations helper module which holds all our custom validations. We can then inject them into our models where necessary. The following code should live in /helpers/validations_helper.rb
in order to be loaded automatically:
- #Michal Gabrukiewicz
- #helpers for validating ActiveRecord instances
- #- load with 'extend' within your model
- module ValidationsHelper
- EMAIL_PATTERN = /^[a-zA-Z][w.-]*[a-zA-Z0-9_]@[a-zA-Z0-9][w.-]*[a-zA-Z0-9].[a-zA-Z][a-zA-Z.]*[a-zA-Z]$/
- DISALLOWED_EMAIL_HOSTS = %w(mailinator.com mailinator.org)
- #validates if given attributes are syntactically valid emails
- #- last parameter can be a hash with options
- # - :allow_all_hosts indicates if every host is allowed. if false then its checked
- # against the list DISALLOWED_EMAIL_HOSTS and returns fals if the email is
- # from one of those. default = false
- def validates_email(*attrs)
- config = {:message => 'is no valid email address', :on => :save, :allow_all_hosts => false}
- config.update(attrs.pop) if attrs.last.is_a?(Hash)
- validates_each(attrs, config) do |record, attr, value|
- unless config[:if] and not evaluate_condition(config[:if], record)
- #do every check only if there was no error yet...
- error = false
- error = record.errors.add(attr, config[:message]) unless not error and value =~ EMAIL_PATTERN
- error = record.errors.add(attr, config[:message]) if not config[:allow_all_hosts] and not error and DISALLOWED_EMAIL_HOSTS.include?(value.split("@", 2)[1].strip.downcase)
- end
- end
- end
- end
If you now want to validate e.g. the email
attribute of a User
model, do it like you used to do with the existing validators:
- class User
- extend ValidationsHelper
- validates_email :email
- end
It still supports all the options which you know from all other validators. So you can specify your own message with :message
, use a condition with :if
, etc. There is one additional option :allow_all_hosts
which prevents the validator to check against the disallowed hosts (all email hosts would be allowed then).
have fun with it and feel free to comment improvements, suggestions, comlaints, etc…
if you are looking for more validators and/or more information about them check Custom validations in rails from Greg
michal - RaRoR (rock and roll ruby on rails)