Module: ActiveModel::Validations::ClassMethods
- Defined in:
- lib/active_model/validations.rb,
lib/active_model/validations/with.rb,
lib/active_model/validations/validates.rb
Instance Method Summary collapse
-
#attribute_method?(attribute) ⇒ Boolean
Check if method is an attribute method or not.
-
#inherited(base) ⇒ Object
Copy validators on inheritance.
-
#validate(*args, &block) ⇒ Object
Adds a validation method or block to the class.
-
#validates(*attributes) ⇒ Object
This method is a shortcut to all default validators and any custom validator classes ending in ‘Validator’.
-
#validates_each(*attr_names, &block) ⇒ Object
Validates each attribute against a block.
-
#validates_with(*args, &block) ⇒ Object
Passes the record off to the class or classes specified and allows them to add errors based on more complex conditions.
-
#validators ⇒ Object
List all validators that are being used to validate the model using
validates_with
method. -
#validators_on(*attributes) ⇒ Object
List all validators that being used to validate a specific attribute.
Instance Method Details
#attribute_method?(attribute) ⇒ Boolean
Check if method is an attribute method or not.
156 157 158 |
# File 'lib/active_model/validations.rb', line 156 def attribute_method?(attribute) method_defined?(attribute) end |
#inherited(base) ⇒ Object
Copy validators on inheritance.
161 162 163 164 165 |
# File 'lib/active_model/validations.rb', line 161 def inherited(base) dup = _validators.dup base._validators = dup.each { |k, v| dup[k] = v.dup } super end |
#validate(*args, &block) ⇒ Object
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
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
Or with a block where self points to the current record to be validated:
class Comment
include ActiveModel::Validations
validate do
errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee)
end
end
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/active_model/validations.rb', line 131 def validate(*args, &block) = args. if .key?(:on) = .dup [:if] = Array.wrap([:if]) [:if].unshift("validation_context == :#{[:on]}") end args << set_callback(:validate, *args, &block) end |
#validates(*attributes) ⇒ Object
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] << ([: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
Additionally validator classes may be in another namespace and still used within any class.
validates :name, :'file/title' => true
The validators hash can also handle regular expressions, ranges, arrays and strings in shortcut form, e.g.
validates :email, :format => /@/
validates :gender, :inclusion => %w(male female)
validates :password, :length => 6..20
When using shortcut form, ranges and arrays are passed to your validator’s initializer as options[:in]
while other types including regular expressions and strings are passed as options[:with]
Finally, the options :if
, :unless
, :on
, :allow_blank
and :allow_nil
can be given to one specific validator, as a hash:
validates :password, :presence => { :if => :password_required? }, :confirmation => true
Or to all at the same time:
validates :password, :presence => true, :confirmation => true, :if => :password_required?
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/active_model/validations/validates.rb', line 82 def validates(*attributes) defaults = attributes. validations = defaults.slice!(*_validates_default_keys) raise ArgumentError, "You need to supply at least one attribute" if attributes.empty? raise ArgumentError, "You need to supply at least one validation" if validations.empty? defaults.merge!(:attributes => attributes) validations.each do |key, | key = "#{key.to_s.camelize}Validator" begin validator = key.include?('::') ? key.constantize : const_get(key) rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end validates_with(validator, defaults.merge(())) end end |
#validates_each(*attr_names, &block) ⇒ Object
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 the context where this validation is active (e.g.:on => :create
or:on => :custom_validation_context
) -
:allow_nil
- Skip validation if attribute isnil
. -
: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.
86 87 88 89 |
# File 'lib/active_model/validations.rb', line 86 def validates_each(*attr_names, &block) = attr_names..symbolize_keys validates_with BlockValidator, .merge(:attributes => attr_names.flatten), &block end |
#validates_with(*args, &block) ⇒ Object
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:
-
:on
- Specifies when this validation is active (:create
or:update
-
: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.
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)
[:my_custom_key] # => "my custom value"
end
end
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/active_model/validations/with.rb', line 79 def validates_with(*args, &block) = args. args.each do |klass| validator = klass.new(, &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, ) end end |
#validators ⇒ Object
List all validators that are being used to validate the model using validates_with
method.
144 145 146 |
# File 'lib/active_model/validations.rb', line 144 def validators _validators.values.flatten.uniq end |
#validators_on(*attributes) ⇒ Object
List all validators that being used to validate a specific attribute.
149 150 151 152 153 |
# File 'lib/active_model/validations.rb', line 149 def validators_on(*attributes) attributes.map do |attribute| _validators[attribute.to_sym] end.flatten end |