Ruby on Rails 4. Model conditional validations - ruby-on-rails

I have model with some validation rules:
class Order < ActiveRecord::Base
validates :zip_code, presence: true, length: {is: 5}, numericality: {only_integer: true, :greater_than => 0}
end
And when zip_code is blank i don't need to perform other zip_code validations (it is redundant and all other validation messages on user page look very strange if zip_code is blank)
How can i implement this logic? i need to validate length, is_integer and greater_than only if zip_code is not blank? and i need to show only zip_code can't be blank message on user page

You can do something like
validates :zip_code, presence: true
validates :zip_code, length: {is: 5}, numericality: {only_integer: true, :greater_than => 0}, :if => :zip_code?
Hope it helps!

Related

activerecords validation in ruby on rails showing multiple outputs

I want to validate the presence of a filed called age. Age can not be blank and should be a number.
Here is my code snipped
validates_presence_of :age
validates :age, numericality: true
its working fine .But my problem is when age is blank output shows
age can't be blank
age is not a number
i don't want to print "age is not a number" when age is blank
You can use allow_blank: true to skip the validation on numericality when the age is blank.
validates :age, numericality: true, allow_blank: true
You can further merge those two validations into one
validates :age, presence: true, numericality: {allow_blank: true}
There is a similar article here
try this
validates_presence_of :age
validates :age, numericality: true, allow_blank: true

Rails custom validation one after another

I have a password field and that validates presence and length and both are working fine. But when I submit the form with blank password field, it displays error messages for both validations.
What I want is if the password is blank then length validator must not checked and display error message for only presence validator. Length validator will only be checked if password is present.
You can use Object#with_options and ActiveRecord::Base#new_record?:
class User < ActiveRecord::Base
with_options :if => :new_record? do |user|
user.validates :password, presence: true, length: { maximum: 20 }
end
end
Look rails conditional validation.
Along with other validations pass this
:allow_blank => true
For example
validates :password, :presence => true, :length => { :maximum => 20, :allow_blank => true }

How to make a validation rails

I want to add a validation in my model of rails: The local team must be different the visiting team.local_team_id is an integer that represent a team and the same for visiting_team_id.This is my code:
class Match < ActiveRecord::Base
validates :mathdate, :presence => true
validate :mydate_is_date?
validates :stage, :presence => true
validates :stage, numericality: {only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 6}
validates :state, :presence => true
validates :state, numericality: {only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 3}
validates :local_team_id, :presence => true
validates :visiting_team_id, :presence => true
validates :stadium_id, :presence => true
def mydate_is_date?
errors.add(:contructiondate, 'must be a valid date') if !mathdate.is_a?(Date)
end
Hope you can help me
Thanks
You can add a validation in Rails like so:
validate :team_ids
def team_ids
# if you want to allow blank / nil values
return if local_team_id.nil? && visiting_team_id.nil?
if local_team_id == visiting_team_id
errors.add(:local_team_id, "can't be equal to visiting_team_id")
errors.add(:visiting_team_id, "can't be equal to local_team_id")
end
end

Validate presence of field only if another field is blank - Rails

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 }

Rails: Validating min and max length of a string but allowing it to be blank

I have a field that I would like to validate. I want the field to be able to be left blank, but if a user is entering data I want it to be in a certain format. Currently I am using the below validations in the model, but this doesn't allow the user to leave it blank:
validates_length_of :foo, :maximum => 5
validates_length_of :foo, :minimum => 5
How do I write this to accomplish my goal?
You can also use this format:
validates :foo, length: {minimum: 5, maximum: 5}, allow_blank: true
Or since your min and max are the same, the following will also work:
validates :foo, length: {is: 5}, allow_blank: true
I think it might need something like:
validates_length_of :foo, minimum: 5, maximum: 5, allow_blank: true
More examples: ActiveRecord::Validations::ClassMethods
Or even more concise (with the new hash syntax), from the validates documentation:
validates :foo, length: 5..5, allow_blank: true
The upper limit should probably represent somehting more meaningful like "in: 5..20", but just answering the question to the letter.
From the validates_length_of documentation:
validates_length_of :phone, :in => 7..32, :allow_blank => true
:allow_blank - Attribute may be blank; skip validation.
every validates_* accepts :if or :unless options
validates_length_of :foo, :maximum => 5, :if => :validate_foo_condition
where validate_foo_condition is method that returns true or false
you can also pass a Proc object:
validates_length_of :foo, :maximum => 5, :unless => Proc.new {|object| object.foo.blank?}
validates_length_of :reason, minimum: 3, maximum: 30
rspec for the same is
it { should validate_length_of(:reason).is_at_least(3).is_at_most(30) }
How about that:
validates_length_of :foo, is: 3, allow_blank: true
Add in your model:
validates :color, length: { is: 7 }
color is a string:
t.string :color, null: false, default: '#0093FF', limit: 7
In your model e.g.
def validate
errors.add_to_base 'error message' unless self.foo.length == 5 or self.foo.blanc?
end

Resources