We can validate email by doing:
validates :email, format: { with: VALID_EMAIL_REGEX }
or
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create
What is the difference between the 2 approaches. Is one approach better than the other?
There is no difference between those two forms. The first is just a convenient shortcut for being able to specify multiple validations on a single attribute. For example, let's say you wanted to ensure that an email is valid but also unique. Using the second form in your example, this would be written
validates_uniqueness_of :email
validates_format_of :email, with: VALID_EMAIL_REGEX
Or, it could be written more succinctly using validates
validates :email, uniqueness: true, format: { with: VALID_EMAIL_REGEX }
What's also nice about using validates is that you can mix default validations with your own custom validations with a single call to validates. More information here.
Related
I am trying to validate fields in a form where I want two different messages for two different problems with the input.
I have the following code:
validates_format_of :email,
:with => /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i,
:allow_blank => false
If the email field is left blank then the error message "Email is invalid" is shown in the website.
How can I get the validation to return a message saying the field cannot be blank if it is left out by the user, instead of just saying it is too short?
I like to handle this with 2 different validations (and make sure they don't both fire at the same time). So something like this:
validates_format_of :email,
:with => /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i,
:allow_blank => true
validates_presence_of :email
The validates_presence_of handles making sure the email is not blank. And changing validates_format_of to use :allow_blank => true will make sure the formatting validation won't run if the email is blank.
In Rails 3.0+ you can also combine the two validations into a single one using validates:
validates :email,
presence: true,
format: { with: /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i,
allow_blank: true }
You create a separate validation for the blank case:
validates_presence_of :email
validates_format_of :email,
:with => /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i,
:allow_blank => true
You need to add another validation checking for presence separately, like:
validates :email, presence: true, format: { with: YOUR_REGEX }
I am using this block of code for validating email address. The format of entered email address validates well, but the problem is with the "uniqueness" part - I currently can enter more identic email addresses to the database - how is that possible?
Has something changed in Rails 4 about validations?
class BetaAccess < ActiveRecord::Base
validates_format_of :email,:with => Devise::email_regexp, uniqueness: true
end
Thank you.
Try this:
class BetaAccess < ActiveRecord::Base
validates :email,format: {with: Devise::email_regexp}, uniqueness: true
end
format and uniqueness are different validators, if you want to use in one line, you should use validates method.
validates :email, :format => { :with => Devise::email_regexp }, :uniqueness => true
validates_format_of :email,:with => Devise::email_regexp, uniqueness: true
combines uniqueness into the validation for format. Use the validates syntax
validates :email,format: {with: Devise::email_regexp},
uniqueness: true
Also, use the new ruby syntax for hashes. Kind of neat that way
I have now this validate for my User model:
validates :email,
presence: true,
uniqueness: { :case_sensitive => false }
I'd like to add :on create for the uniqueness as users are definitely allowed to update their email by putting the same email!
Should I write it this way? I'm afraid the on:create also applies to the presence:true but it should only apply to the uniqueness validation:
validates :email,
presence: true,
uniqueness: { :case_sensitive => false }, on: :create
I would like to say some logic. Email should be unique and user will be identified by his email. So while update, there is no need to put email field where user can edit the email value. You can make the email field as readonly, so that user can not change it while updating the profile.
And yes, the syntax on: :create is the nice solution for it.
yes it will applied on both you can use separate validation for that
validates :email, presence: true
validates :email, uniqueness: { :case_sensitive => false }, on: :create
I validate fields in model using:
validates :first_name, :presence => true, :if => :should_validate?
validates :last_name, :presence => true, :if => :should_validate?
...
There are many fields in model that needs to be validated and it doesn't look good if I specify :if => method for each one.
Is it possible to embed this validates methods in block instead of giving :if => method for each one?
You could write your own custom validator of course, but if you're only validating presence, this might do the trick:
validates :first_name, :last_name, :presence => true, :if => :should_validate?
I don't think there is something out of the box for this. If you want, you can use a custom validator.
What are the conditions that you need this validated? If you don't need it validated couldn't you just leave that line out? Otherwise you could just validate on certain actions so you don't need to evaluate for should_validate?, for example:
validates :first_name, :last_name, :presence => true, :only => [:create, :update]
I have a form with a mobile/cell number and a home phone number.
I want to have only validate presence of mobile/cell number if the phone number has been left blank or vice versa.
My current validations for these fields are as follows.
validates_presence_of :mobile_number
validates_presence_of :home_phone
validates_length_of :home_phone, :minimum => 12, :maximum => 12
validates_length_of :mobile_number, :minimum => 10, :maximum => 10, :allow_blank => true
validates_format_of :home_phone, :with => /\A[0-9]{2}\s[0-9]{4}\s[0-9]{4}/, :message => "format should be 02 9999 9999"
I thought I could have something like the following but not sure how to do this exactly.
validates_presence_of :mobile_number, :unless => :home_phone.blank?
I'm using Rails 3.
You don't need a lambda. This will do:
validates_presence_of :mobile_number, :unless => :home_phone?
Also, all of the validators take the same if/unless options, so you can make them conditional at will.
Update: Looking back at this answer a few days later, I see that I should explain why it works:
If you set a validator's :unless option to be a symbol, Rails will look for an instance method of that name, invoke that method on the instance that's being validated -- at validation time -- and only perform the validation if the method returns false.
ActiveRecord automatically creates question mark methods for each of your model's attributes, so the existence of a home_phone column in your model's table causes Rails to create a handy #home_phone? method. This method returns true if and only if home_phone is present (i.e. not blank). If the home_phone attribute is nil or an empty string or a bunch of white space, home_phone? will return false.
UPDATE: Confirmed that this old technique continues to work in Rails 5.
You must use a lambda / Proc object:
validates_presence_of :mobile_number, :unless => lambda { self.home_phone.blank? }
Starting in Rails 4, you can pass a block to presence. Concisely:
validates :mobile_number, presence: {unless: :home_phone?}
Also, :home_phone? returns false for nil or blank.
Here is another way that works in rails 4
validates_presence_of :job, if: :executed_at?
validates :code,
presence: true,
length: { minimum: 10, maximum: 50 },
uniqueness: { case_sensitive: false },
numericality: { only_integer: true }
a short solution:
validates_presence_of :mobile_number, unless: -> { home_phone.blank? }
In newer versions of Rails, instead of relying on old validates_presence_of, you should use validates and list validations for each attribute:
validates :mobile_number, presence: { if: -> { home_phone.present? } }
Tested in Rails 7, this works flawlessly:
validates :mobile_number, presence: { unless: :home_phone }