diff options
Diffstat (limited to 'activemodel/lib/active_model/validations')
7 files changed, 37 insertions, 35 deletions
diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb index 22a77320dc..c39c85e1af 100644 --- a/activemodel/lib/active_model/validations/callbacks.rb +++ b/activemodel/lib/active_model/validations/callbacks.rb @@ -23,14 +23,14 @@ module ActiveModel included do include ActiveSupport::Callbacks - define_callbacks :validation, :terminator => "result == false", :scope => [:kind, :name] + define_callbacks :validation, :terminator => "result == false", :skip_after_callbacks_if_terminated => true, :scope => [:kind, :name] end module ClassMethods def before_validation(*args, &block) options = args.last if options.is_a?(Hash) && options[:on] - options[:if] = Array.wrap(options[:if]) + options[:if] = Array(options[:if]) options[:if].unshift("self.validation_context == :#{options[:on]}") end set_callback(:validation, :before, *args, &block) @@ -39,8 +39,7 @@ module ActiveModel def after_validation(*args, &block) options = args.extract_options! options[:prepend] = true - options[:if] = Array.wrap(options[:if]) - options[:if] << "!halted" + options[:if] = Array(options[:if]) options[:if].unshift("self.validation_context == :#{options[:on]}") if options[:on] set_callback(:validation, :after, *(args << options), &block) end diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index 6573a7d264..e8526303e2 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -37,7 +37,7 @@ module ActiveModel # attribute. # # NOTE: This check is performed only if +password_confirmation+ is not - # +nil+, and by default only on save. To require confirmation, make sure + # +nil+. To require confirmation, make sure # to add a presence check for the confirmation attribute: # # validates_presence_of :password_confirmation, :if => :password_changed? diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb index eb7aac709d..f1beddf6d4 100644 --- a/activemodel/lib/active_model/validations/length.rb +++ b/activemodel/lib/active_model/validations/length.rb @@ -6,14 +6,12 @@ module ActiveModel MESSAGES = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }.freeze CHECKS = { :is => :==, :minimum => :>=, :maximum => :<= }.freeze - DEFAULT_TOKENIZER = lambda { |value| value.split(//) } RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :tokenizer, :too_short, :too_long] def initialize(options) if range = (options.delete(:in) || options.delete(:within)) raise ArgumentError, ":in and :within must be a Range" unless range.is_a?(Range) - options[:minimum], options[:maximum] = range.begin, range.end - options[:maximum] -= 1 if range.exclude_end? + options[:minimum], options[:maximum] = range.min, range.max end super @@ -23,27 +21,24 @@ module ActiveModel keys = CHECKS.keys & options.keys if keys.empty? - raise ArgumentError, 'Range unspecified. Specify the :within, :maximum, :minimum, or :is option.' + raise ArgumentError, 'Range unspecified. Specify the :in, :within, :maximum, :minimum, or :is option.' end keys.each do |key| value = options[key] - unless value.is_a?(Integer) && value >= 0 - raise ArgumentError, ":#{key} must be a nonnegative Integer" + unless value.is_a?(Integer) && value >= 0 or value == Float::INFINITY + raise ArgumentError, ":#{key} must be a nonnegative Integer or Infinity" end end end def validate_each(record, attribute, value) - value = (options[:tokenizer] || DEFAULT_TOKENIZER).call(value) if value.kind_of?(String) + value = tokenize(value) + value_length = value.respond_to?(:length) ? value.length : value.to_s.length CHECKS.each do |key, validity_check| next unless check_value = options[key] - - value ||= [] if key == :maximum - - value_length = value.respond_to?(:length) ? value.length : value.to_s.length next if value_length.send(validity_check, check_value) errors_options = options.except(*RESERVED_OPTIONS) @@ -55,6 +50,14 @@ module ActiveModel record.errors.add(attribute, MESSAGES[key], errors_options) end end + + private + + def tokenize(value) + if options[:tokenizer] && value.kind_of?(String) + options[:tokenizer].call(value) + end || value + end end module HelperMethods @@ -96,7 +99,7 @@ module ActiveModel # * <tt>:tokenizer</tt> - Specifies how to split up the attribute string. (e.g. <tt>:tokenizer => lambda {|str| str.scan(/\w+/)}</tt> to # count words as in above example.) # Defaults to <tt>lambda{ |value| value.split(//) }</tt> which counts individual characters. - # * <tt>:strict</tt> - Specifies whether validation should be strict. + # * <tt>:strict</tt> - Specifies whether validation should be strict. # See <tt>ActiveModel::Validation#validates!</tt> for more information def validates_length_of(*attr_names) validates_with LengthValidator, _merge_attributes(attr_names) diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 34d447a0fa..bb9f9679fc 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -5,7 +5,7 @@ module ActiveModel class NumericalityValidator < EachValidator CHECKS = { :greater_than => :>, :greater_than_or_equal_to => :>=, :equal_to => :==, :less_than => :<, :less_than_or_equal_to => :<=, - :odd => :odd?, :even => :even? }.freeze + :odd => :odd?, :even => :even?, :other_than => :!= }.freeze RESERVED_OPTIONS = CHECKS.keys + [:only_integer] @@ -99,6 +99,7 @@ module ActiveModel # * <tt>:equal_to</tt> - Specifies the value must be equal to the supplied value. # * <tt>:less_than</tt> - Specifies the value must be less than the supplied value. # * <tt>:less_than_or_equal_to</tt> - Specifies the value must be less than or equal the supplied value. + # * <tt>:other_than</tt> - Specifies the value must be other than the supplied value. # * <tt>:odd</tt> - Specifies the value must be an odd number. # * <tt>:even</tt> - Specifies the value must be an even number. # * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should @@ -107,7 +108,7 @@ module ActiveModel # * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The # method, proc or string should return or evaluate to a true or false value. - # * <tt>:strict</tt> - Specifies whether validation should be strict. + # * <tt>:strict</tt> - Specifies whether validation should be strict. # See <tt>ActiveModel::Validation#validates!</tt> for more information # # The following checks can also be supplied with a proc or a symbol which corresponds to a method: diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index 35af7152db..9a643a6f5c 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -25,14 +25,14 @@ module ActiveModel # This is due to the way Object#blank? handles boolean values: <tt>false.blank? # => true</tt>. # # Configuration options: - # * <tt>message</tt> - A custom error message (default is: "can't be blank"). + # * <tt>:message</tt> - A custom error message (default is: "can't be blank"). # * <tt>:on</tt> - Specifies when this validation is active. Runs in all # validation contexts by default (+nil+), other options are <tt>:create</tt> # and <tt>:update</tt>. - # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should # occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). # The method, proc or string should return or evaluate to a true or false value. - # * <tt>unless</tt> - Specifies a method, proc or string to call to determine if the validation should + # * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should # not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). # The method, proc or string should return or evaluate to a true or false value. # * <tt>:strict</tt> - Specifies whether validation should be strict. diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index fbceb81e8f..d94c4e3f4f 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -1,7 +1,6 @@ require 'active_support/core_ext/hash/slice' module ActiveModel - # == Active Model validates method module Validations module ClassMethods @@ -57,9 +56,9 @@ module ActiveModel # # Additionally validator classes may be in another namespace and still used within any class. # - # validates :name, :'file/title' => true + # validates :name, :'film/title' => true # - # The validators hash can also handle regular expressions, ranges, + # The validators hash can also handle regular expressions, ranges, # arrays and strings in shortcut form, e.g. # # validates :email, :format => /@/ @@ -70,7 +69,7 @@ module ActiveModel # 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+, +:allow_nil+ and +:strict+ + # Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+ and +:strict+ # can be given to one specific validator, as a hash: # # validates :password, :presence => { :if => :password_required? }, :confirmation => true @@ -80,7 +79,7 @@ module ActiveModel # validates :password, :presence => true, :confirmation => true, :if => :password_required? # def validates(*attributes) - defaults = attributes.extract_options! + defaults = attributes.extract_options!.dup validations = defaults.slice!(*_validates_default_keys) raise ArgumentError, "You need to supply at least one attribute" if attributes.empty? @@ -101,12 +100,12 @@ module ActiveModel end end - # This method is used to define validation that can not be corrected by end user - # and is considered exceptional. - # So each validator defined with bang or <tt>:strict</tt> option set to <tt>true</tt> - # will always raise <tt>ActiveModel::InternalValidationFailed</tt> instead of adding error - # when validation fails - # See <tt>validates</tt> for more information about validation itself. + # This method is used to define validations that cannot be corrected by end + # users and are considered exceptional. So each validator defined with bang + # or <tt>:strict</tt> option set to <tt>true</tt> will always raise + # <tt>ActiveModel::StrictValidationFailed</tt> instead of adding error + # when validation fails. + # See <tt>validates</tt> for more information about the validation itself. def validates!(*attributes) options = attributes.extract_options! options[:strict] = true @@ -118,7 +117,7 @@ module ActiveModel # 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 , :strict] + [:if, :unless, :on, :allow_blank, :allow_nil , :strict] end def _parse_validates_options(options) #:nodoc: diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 93a340eb39..72b8562b93 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -56,7 +56,7 @@ module ActiveModel # if the validation should occur (e.g. <tt>:if => :allow_validation</tt>, # or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). # The method, proc or string should return or evaluate to a true or false value. - # * <tt>unless</tt> - Specifies a method, proc or string to call to + # * <tt>:unless</tt> - Specifies a method, proc or string to call to # determine if the validation should not occur # (e.g. <tt>:unless => :skip_validation</tt>, or # <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). |