module ActiveModel::Validations::ClassMethods
def _parse_validates_options(options) #:nodoc:
def _parse_validates_options(options) #:nodoc: case options when TrueClass {} when Hash options when Regexp { :with => options } when Range, Array { :in => options } else raise ArgumentError, "#{options.inspect} is an invalid option. Expecting true, Hash, Regexp, Range, or Array" end end
def attribute_method?(attribute)
def attribute_method?(attribute) method_defined?(attribute) end
def inherited(base)
def inherited(base) dup = _validators.dup base._validators = dup.each { |k, v| dup[k] = v.dup } super end
def validate(*args, &block)
end
end
errors.add(:base, ("Must be friends to leave a comment") unless commenter.friend_of?(commentee)
def must_be_friends
end
comment.must_be_friends
validate do |comment|
include ActiveModel::Validations
class Comment
Or with a block which is passed with the current record to be validated:
end
end
errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee)
def must_be_friends
validate :must_be_friends
include ActiveModel::Validations
class Comment
This can be done with a symbol pointing to a method:
you're looking for more descriptive declaration of your validations.
overriding the +validate+ instance method becomes too unwieldy and
Adds a validation method or block to the class. This is useful when
def validate(*args, &block) options = args.extract_options! if options.key?(:on) options = options.dup options[:if] = Array.wrap(options[:if]) options[:if] << "validation_context == :#{options[:on]}" end args << options set_callback(:validate, *args, &block) end
def validates(*attributes)
validates :password, :presence => true, :confirmation => true, :if => :password_required?
Or to all at the same time:
validates :password, :presence => { :if => :password_required? }, :confirmation => true
to one specific validator:
Finally, the options :if, :unless, :on, :allow_blank and :allow_nil can be given
validates :password, :length => 6..20
validates :gender, :inclusion => %w(male female)
validates :email, :format => /@/
The validators hash can also handle regular expressions, ranges and arrays:
end
validates :name, :title => true
end
end
record.errors[attribute] << "must start with 'the'" unless value =~ /\Athe/i
def validate_each(record, attribute, value)
class TitleValidator < ActiveModel::EachValidator
include ActiveModel::Validations
class Film
allowing custom modules of validators to be included as needed e.g.
Validator classes may also exist within the class being validated
end
validates :email, :presence => true, :email => true
validates :name, :presence => true, :uniqueness => true, :length => { :maximum => 100 }
attr_accessor :name, :email
include ActiveModel::Validations
class Person
end
end
value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
record.errors[attribute] << (options[:message] || "is not an email") unless
def validate_each(record, attribute, value)
class EmailValidator < ActiveModel::EachValidator
and default validators in one call for a given attribute e.g.
The power of the +validates+ method comes when using custom validators
validates :username, :uniqueness => true
validates :username, :presence => true
validates :age, :numericality => true
validates :first_name, :length => { :maximum => 30 }
validates :age, :inclusion => { :in => 0..9 }
validates :email, :format => { :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create }
validates :username, :exclusion => { :in => %w(admin superuser) }
validates :password, :confirmation => true
validates :terms, :acceptance => true
Examples of using the default rails validators:
custom validator classes in their place such as PresenceValidator.
validators can be overridden inside specific classes by creating
validator classes ending in 'Validator'. Note that Rails default
This method is a shortcut to all default validators and any custom
def validates(*attributes) defaults = attributes.extract_options! validations = defaults.slice!(:if, :unless, :on, :allow_blank, :allow_nil) raise ArgumentError, "You need to supply at least one attribute" if attributes.empty? raise ArgumentError, "Attribute names must be symbols" if attributes.any?{ |attribute| !attribute.is_a?(Symbol) } raise ArgumentError, "You need to supply at least one validation" if validations.empty? defaults.merge!(:attributes => attributes) validations.each do |key, options| begin validator = const_get("#{key.to_s.camelize}Validator") rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end validates_with(validator, defaults.merge(_parse_validates_options(options))) end end
def validates_each(*attr_names, &block)
:unless => Proc.new { |user| user.signup_step <= 2 }). The
not occur (e.g. :unless => :skip_validation, or
* :unless - Specifies a method, proc or string to call to determine if the validation should
proc or string should return or evaluate to a true or false value.
or :if => Proc.new { |user| user.signup_step > 2 }). The method,
if the validation should occur (e.g. :if => :allow_validation,
* :if - Specifies a method, proc or string to call to determine
* :allow_blank - Skip validation if attribute is blank.
* :allow_nil - Skip validation if attribute is +nil+.
:save, other options :create, :update).
* :on - Specifies when this validation is active (default is
Options:
end
end
record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z
validates_each :first_name, :last_name do |record, attr, value|
attr_accessor :first_name, :last_name
include ActiveModel::Validations
class Person
Validates each attribute against a block.
def validates_each(*attr_names, &block) options = attr_names.extract_options!.symbolize_keys validates_with BlockValidator, options.merge(:attributes => attr_names.flatten), &block end
def validates_with(*args, &block)
end
end
options[:my_custom_key] # => "my custom value"
def validate(record)
class MyValidator < ActiveModel::Validator
end
validates_with MyValidator, :my_custom_key => "my custom value"
include ActiveModel::Validations
class Person
to the class and available as options:
If you pass any additional configuration options, they will be passed
The method, proc or string should return or evaluate to a true or false value.
:unless => Proc.new { |user| user.signup_step <= 2 }).
(e.g. :unless => :skip_validation, or
determine if the validation should not occur
* unless - Specifies a method, proc or string to call to
The method, proc or string should return or evaluate to a true or false value.
or :if => Proc.new { |user| user.signup_step > 2 }).
if the validation should occur (e.g. :if => :allow_validation,
* if - Specifies a method, proc or string to call to determine
(:create or :update
* on - Specifies when this validation is active
Configuration options:
end
validates_with MyValidator, MyOtherValidator, :on => :create
include ActiveModel::Validations
class Person
You may also pass it multiple classes, like so:
end
end
# ...
def some_complex_logic
private
end
end
record.errors[:base] << "This record is invalid"
if some_complex_logic
def validate(record)
class MyValidator < ActiveModel::Validator
end
validates_with MyValidator
include ActiveModel::Validations
class Person
to add errors based on more complex conditions.
Passes the record off to the class or classes specified and allows them
def validates_with(*args, &block) options = args.extract_options! args.each do |klass| validator = klass.new(options, &block) validator.setup(self) if validator.respond_to?(:setup) if validator.respond_to?(:attributes) && !validator.attributes.empty? validator.attributes.each do |attribute| _validators[attribute.to_sym] << validator end else _validators[nil] << validator end validate(validator, options) end end
def validators
List all validators that are being used to validate the model using
def validators _validators.values.flatten.uniq end
def validators_on(attribute)
def validators_on(attribute) _validators[attribute.to_sym] end