mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
126 lines
4.7 KiB
Ruby
126 lines
4.7 KiB
Ruby
require 'active_support/core_ext/hash/slice'
|
|
|
|
module ActiveModel
|
|
|
|
# == Active Model validates method
|
|
module Validations
|
|
module ClassMethods
|
|
# 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
|
|
#
|
|
# 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?
|
|
#
|
|
def validates(*attributes)
|
|
defaults = attributes.extract_options!
|
|
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, options|
|
|
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(_parse_validates_options(options)))
|
|
end
|
|
end
|
|
|
|
protected
|
|
|
|
# When creating custom validators, it might be useful to be able to specify
|
|
# additional default keys. This can be done by overwriting this method.
|
|
def _validates_default_keys
|
|
[ :if, :unless, :on, :allow_blank, :allow_nil ]
|
|
end
|
|
|
|
def _parse_validates_options(options) #:nodoc:
|
|
case options
|
|
when TrueClass
|
|
{}
|
|
when Hash
|
|
options
|
|
when Range, Array
|
|
{ :in => options }
|
|
else
|
|
{ :with => options }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|