Module | ActiveModel::Validations::ClassMethods |
In: |
lib/active_model/validations/with.rb
lib/active_model/validations/validates.rb lib/active_model/validations.rb |
Adds a validation method or block to the class. This is useful when overriding the validate instance method becomes too unwieldy and you‘re looking for more descriptive declaration of your validations.
This can be done with a symbol pointing to a method:
class Comment include ActiveModel::Validations validate :must_be_friends def must_be_friends errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee) end end
Or with a block which is passed with the current record to be validated:
class Comment include ActiveModel::Validations validate do |comment| comment.must_be_friends end def must_be_friends errors.add(:base, ("Must be friends to leave a comment") unless commenter.friend_of?(commentee) end end
This method is a shortcut to all default validators and any custom validator classes ending in ‘Validator’. Note that Rails default validators can be overridden inside specific classes by creating custom validator classes in their place such as PresenceValidator.
Examples of using the default rails validators:
validates :terms, :acceptance => true validates :password, :confirmation => true validates :username, :exclusion => { :in => %w(admin superuser) } validates :email, :format => { :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create } validates :age, :inclusion => { :in => 0..9 } validates :first_name, :length => { :maximum => 30 } validates :age, :numericality => true validates :username, :presence => true validates :username, :uniqueness => true
The power of the validates method comes when using custom validators and default validators in one call for a given attribute e.g.
class EmailValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) record.errors[attribute] << (options[:message] || "is not an email") unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i end end class Person include ActiveModel::Validations attr_accessor :name, :email validates :name, :presence => true, :uniqueness => true, :length => { :maximum => 100 } validates :email, :presence => true, :email => true end
Validator classes may also exist within the class being validated allowing custom modules of validators to be included as needed e.g.
class Film include ActiveModel::Validations class TitleValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) record.errors[attribute] << "must start with 'the'" unless value =~ /\Athe/i end end validates :name, :title => true end
The validators hash can also handle regular expressions, ranges and arrays:
validates :email, :format => /@/ validates :gender, :inclusion => %w(male female) validates :password, :length => 6..20
Finally, the options :if, :unless, :on, :allow_blank and :allow_nil can be given to one specific validator:
validates :password, :presence => { :if => :password_required? }, :confirmation => true
Or to all at the same time:
validates :password, :presence => true, :confirmation => true, :if => :password_required?
Validates each attribute against a block.
class Person include ActiveModel::Validations attr_accessor :first_name, :last_name validates_each :first_name, :last_name do |record, attr, value| record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z end end
Options:
Passes the record off to the class or classes specified and allows them to add errors based on more complex conditions.
class Person include ActiveModel::Validations validates_with MyValidator end class MyValidator < ActiveModel::Validator def validate(record) if some_complex_logic record.errors[:base] << "This record is invalid" end end private def some_complex_logic # ... end end
You may also pass it multiple classes, like so:
class Person include ActiveModel::Validations validates_with MyValidator, MyOtherValidator, :on => :create end
Configuration options:
If you pass any additional configuration options, they will be passed to the class and available as options:
class Person include ActiveModel::Validations validates_with MyValidator, :my_custom_key => "my custom value" end class MyValidator < ActiveModel::Validator def validate(record) options[:my_custom_key] # => "my custom value" end end
List all validators that are being used to validate the model using validates_with method.