validates(*attributes) public

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?
Show source
Register or log in to add new notes.
February 21, 2011 - (>= v3.0.0)
8 thanks

case-insensitive uniqueness

For case-insensitive uniqueness:

validate :username, :uniqueness => {:case_sensitive => false}
June 18, 2010
8 thanks

multiple attributes with the same validations

You can list multiple attributes if they share the same validations

validates :title, :body, :presence => true

sending the attributes as an array will return an error

validates [:title, :body], :presence => true
#=> ArgumentError: Attribute names must be symbols
July 14, 2010
7 thanks

uniqueness

You can scope uniqueness as well

validates :user_name, :presence => true, :uniqueness => {:scope => :account_id}

# the old way  
validates_uniqueness_of :user_name, :scope => :account_id
July 20, 2012 - (>= v3.0.0)
2 thanks

Changing the Message

For Change the default message:

Code example

validates :invoice_number, :presence => {:message => 'The invoice number must be informed.'}
October 7, 2010 - (>= v3.0.0)
2 thanks

Custom validator with i18n support

Here is modified EmailValidator from the example above:

class EmailValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.errors.add(attribute, options[:message] || :email) unless
      value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
  end
end

And locale:

en:
  activerecord:
    errors:
      messages:
        email: "is not an email"
June 16, 2011 - (>= v3.0.0)
1 thank

validating a database column acceptance

accept option should be set to true if you are validating a database column, since the attribute is typecast from “1” to true before validation

validates :terms,
  acceptance: {
    allow_nil: false,
    accept: true
  }
October 21, 2010 - (v3.0.0)
0 thanks

Validate number

option like :greater_than still supported

use like this

Code example

validates :position, :presence => true, :numericality => {:greater_than => 0}

July 1, 2011 - (>= v3.0.0)
0 thanks

Common Validator options

Most validators will support all of the following common options: (Through ActiveModel::Errors::CALLBACK_OPTIONS (http://apidock.com/rails/ActiveModel/Errors))

  • :if

  • :unless

  • :allow_blank

  • :allow_nil

March 5, 2012
0 thanks

Example of conditions using

f.e.

validates :number, :presence => { :if => :quota_file? }

def self.quota_file?
  quota_file?
end
November 6, 2012 - (>= v3.0.0)
0 thanks

attributes that have the same names as options

For reasons that are beyond my comprehension, this piece of code

class Working

  include ActiveModel::Validations

  attr_accessor :format

  validates :format, :presence => true, :format => { :with => /\AWorking/ }

end

works (NOTE: it has an attribute that has the same name of an option), while this

class NotWorking < ActiveRecord::Base

  validates :format, :presence => true, :format => { :with => /\ANot Working/ }

end

does not (assuming that you have a legacy db in which you can’t change the names of the columns). It throws an ArgumentError at you. However, a crude hack is to add an explicit accessor to the :format method, like this

class WorkingAgain < ActiveRecord::Base

  validates :format, :presence => true, :format => { :with => /\AWorking again/ }

  def format
    read_attribute(:format)
  end

end

Any explanation is welcome.