http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html
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
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:
:on - Specifies when this validation is active (default is :save, other options :create, :update).
:allow_nil - Skip validation if attribute is nil.
:allow_blank - Skip validation if attribute is blank.
:if - Specifies a method, proc or string to call to determine if the validation should occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The method, proc or string should return or evaluate to a true or false value.
:unless - Specifies a method, proc or string to call to determine if the validation should not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The method, proc or string should return or evaluate to a true or false value.
u = User.new
u.valid?
u.invalid?
u.valid?(:email)
u.errors
u.errors.on("email")
u.errors.full_messages
u1 = User.new
u1.errors => #<OrderedHash {}>
u1.save => false
u1.errors
=> #<OrderedHash {:password_confirmation=>["is too short (minimum is 4 characters)"], :password=>["is too short (minimum is 4 characters)"], :email=>["is too short (minimum is 6 characters)", "should look like an email address."]}>
u1.errors.add(:email, "is too short")
u1.errors.methods.grep /add/
u1=User.new
u1.errors => #<OrderedHash {}>
u1.valid? => false
u1.errors
=> #<OrderedHash {:password_confirmation=>["is too short (minimum is 4 characters)"], :password=>["is too short (minimum is 4 characters)"], :email=>["is too short (minimum is 6 characters)", "should look like an email address."]}>
u1.errors.delete(:email)
u1.errors
=> #<OrderedHash {:password_confirmation=>["is too short (minimum is 4 characters)"], :password=>["is too short (minimum is 4 characters)"]}>