I have an object that contains a number range and a description [min_val, max_val, name].
I need to validate that min_val < max_val. However, if one of them is blank I get a nil comparison error, instead, I'd like to tell the user that a number is required.
Also, how can I change the error message for numericality?
validates :min_val, :presence => true, :numericality => {:greater_than => 0, :less_than => :max_val}
validates :max_val, :presence => true, :numericality => {:greater_than => 0, :greater_than => :min_val}
validates :name, :presence => true, :if => Proc.new { |r| !r.min_val.nil? || !r.max_val.nil? }
You can use :message to specify a custom error message.
validates :max_val, :presence => true, :numericality => {:greater_than => 0, :message => " is an invalid number."}
validates :min_val, :presence => true, :numericality => {:greater_than => 0, :message => " is an invalid number."}
validate do |record|
record.errors.add_to_base("The min_val should be less than max_val") if min_val.to_i >= max_val.to_i
end
validates :name, :presence => true, :if => Proc.new { |r| !r.min_val.nil? || !r.max_val.nil? }
Related
I validate Realty objects depending on their active_state, so if it's pending, multiple fields are allowed to be blank.
with_options :if => Proc.new { |a| a.active_state == 'pending'} do |realty|
realty.validates :street, :length => {:in => 1..100}, :allow_blank => true
realty.validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}, :allow_blank => true
realty.validates :city, :length => {:in => 1..50}, :allow_blank => true
realty.validates :description, :length => {:maximum => 8000}, :allow_blank => true
realty.validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}, :allow_blank => true
end
with_options :if => Proc.new { |a| a.active_state != 'pending'} do |realty|
realty.validates :street, :length => {:in => 1..100}
realty.validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}
realty.validates :city, :length => {:in => 1..50}
realty.validates :description, :length => {:maximum => 8000}
realty.validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}
end
The only difference are those :allow_blank => true options.
I want to make this code more dry, so my attempt would be to use the normal validations block once:
validates :street, :length => {:in => 1..100}
validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}
validates :city, :length => {:in => 1..50}
validates :description, :length => {:maximum => 8000}
validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}
and then simply call some function on all of those fields in case the state is pending:
with_options :if => Proc.new { |a| a.active_state == 'pending'} do |realty|
realty.allow_blank_of :street, :postalcode, :city, :description, :leasing_costs
end
Similar to all those validates_uniqueness_of :x, :y, :z methods.
I couldn't find a function to fit my need. How can I approach this?
It would be nice if the :allow_blank option took a proc, but I don't think it does. However, you can achieve the same result using the :if option since :allow_blank is essentially a way of saying "if the attribute is blank then don't run this validation requirement". So try this:
with_options :if => Proc.new { |a| a.active_state == 'pending' ? a.present? : true } do |realty|
realty.validates :street, :length => {:in => 1..100}
realty.validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}
realty.validates :city, :length => {:in => 1..50}
realty.validates :description, :length => {:maximum => 8000}
realty.validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}
end
The proc in this case is saying... if the active_state is 'pending' and the attribute is present then execute this validation. But if the active_state is not 'pending' then the attribute isn't allowed to be blank so always run the validation. I hope I got that logic right based on your needs.
From pdobb's answer
However, you can achieve the same result using the :if
option since :allow_blank is essentially a way of saying "if the
attribute is blank then don't run this validation requirement".
Based on pdobbs explanation what allow_blank => true actually does, I could narrow the validations down to:
validates :street, :length => {:in => 1..100}, :unless => :pending?
validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}, :unless => :pending?
validates :city, :length => {:in => 1..50}, :unless => :pending?
validates :description, :length => {:maximum => 8000}, :unless => :pending?
validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}, :unless => :pending?
def pending?
active_state == "pending"
end
So I simply skip all of those validations if the active_state is "pending".
Allot more DRY :)
I haven't ran this, but I think this may work
before_commit :build_callback_validator, :on => :create
def build_callback_validator
validates :street, :length => {:in => 1..100}
validates :postalcode, :numericality => {:only_integer => true}, :length => {:in => 4..5}
validates :city, :length => {:in => 1..50}
validates :description, :length => {:maximum => 8000}
validates :leasing_costs, :numericality => {:only_integer => true}, :length => {:in => 1..9}
if self.active_state != 'pending'
self.allow_blank_of :street, :postalcode, :city, :description, :leasing_costs
end
end
I get this error
Unknown validator: 'MessageValidator'
I have no idea why I'm getting that.
What's wrong with my code?
validates :title,
:presence => true,
:uniqueness => true,
:length => { :maximum => 100 },
:message => "Must be input and has to be less than 100 characters, and unique."
Try:
validates :title,
:presence => {:message => "Title can't be blank." },
:uniqueness => {:message => "Title already exists."},
:length => { :maximum => 100, :message => "Must be less than 100 characters"}
I assume you want the message to be when the length validation fails. You should be including message in that hash like:
validates :title,
:presence => true,
:uniqueness => true,
:length => { :maximum => 100, :message => "Must be less than 100 characters"}
Right now, I have a User model with a username field that's being validated by:
validates :username,
:presence => true,
:length => { :in => 3..60 },
:format => { :with => /^[a-zA-Z0-9\-_ ]+$/ }
How can I hide the :length and :format validation errors if :presence is not met?
Try :allow_blank => true in 2nd and 3rd validations.
I think you can do like this:
validates :username,
:presence => true,
:length => { :in => 3..60, :allow_nil => true },
:format => { :with => /^[a-zA-Z0-9\-_ ]+$/, :allow_nil => true }
It will not care about length and format validations when username is not set, but it will work fine with at least one character typed.
Some validations are repetitive in my models:
validates :name, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
validates :name_seo, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
How would I put that in a mixin? I get this error if I just put 'em in a mixin
app/models/validations.rb:5: undefined method `validates' for Validations:Module (NoMethodError)
module Validations
extend ActiveSupport::Concern
included do
validates :name, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
validates :name_seo, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
end
end
The validates macro must be evaluated in the context of the includer, not of the module (like you probably were doing).
Your module should look something like this:
module CommonValidations
extend ActiveSupport::Concern
included do
validates :name, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
validates :name_seo, :length => { :minimum => 2 }, :presence => true, :uniqueness => true
end
end
Then in your model:
class Post < ActiveRecord::Base
include CommonValidations
...
end
I'm using ActiveSupport::Concern here to make the code a little clearer.
I'm a newbie in rails. how put a validated on password field. specified only on create and used an allow_blank method. but everytime i update it still creates a nil in the password field. any help?
validates :password, :presence => { :on => :create },
:confirmation => true,
:length => { :within => 8..40},
:allow_blank => true,
Try this:
validates :password, :presence => { :if => :new_record? },
:confirmation => true,
:length => { :within => 8..40 }