aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/lib/active_model/validations/numericality.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel/lib/active_model/validations/numericality.rb')
-rw-r--r--activemodel/lib/active_model/validations/numericality.rb105
1 files changed, 54 insertions, 51 deletions
diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb
index 32dbcd82d0..8ffa395a2d 100644
--- a/activemodel/lib/active_model/validations/numericality.rb
+++ b/activemodel/lib/active_model/validations/numericality.rb
@@ -1,9 +1,55 @@
module ActiveModel
module Validations
+ 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
+
+ def validate_each(record, attr_name, value)
+ before_type_cast = "#{attr_name}_before_type_cast"
+
+ if record.respond_to?(before_type_cast.to_sym)
+ raw_value = record.send("#{attr_name}_before_type_cast") || value
+ else
+ raw_value = value
+ end
+
+ return if options[:allow_nil] and raw_value.nil?
+
+ if options[:only_integer]
+ unless raw_value.to_s =~ /\A[+-]?\d+\Z/
+ record.errors.add(attr_name, :not_a_number, :value => raw_value, :default => options[:message])
+ return
+ end
+ raw_value = raw_value.to_i
+ else
+ begin
+ raw_value = Kernel.Float(raw_value)
+ rescue ArgumentError, TypeError
+ record.errors.add(attr_name, :not_a_number, :value => raw_value, :default => options[:message])
+ return
+ end
+ end
+
+ options.slice(*CHECKS.keys).each do |option, option_value|
+ case option
+ when :odd, :even
+ unless raw_value.to_i.method(CHECKS[option])[]
+ record.errors.add(attr_name, option, :value => raw_value, :default => options[:message])
+ end
+ else
+ option_value = option_value.call(record) if option_value.is_a? Proc
+ option_value = record.method(option_value).call if option_value.is_a? Symbol
+
+ unless raw_value.method(CHECKS[option])[option_value]
+ record.errors.add(attr_name, option, :default => options[:message], :value => raw_value, :count => option_value)
+ end
+ end
+ end
+ end
+ end
module ClassMethods
- ALL_NUMERICALITY_CHECKS = { :greater_than => '>', :greater_than_or_equal_to => '>=',
- :equal_to => '==', :less_than => '<', :less_than_or_equal_to => '<=',
- :odd => 'odd?', :even => 'even?' }.freeze
+
# Validates whether the value of the specified attribute is numeric by trying to convert it to
# a float with Kernel.Float (if <tt>only_integer</tt> is false) or applying it to the regular expression
@@ -44,61 +90,18 @@ module ActiveModel
# validates_numericality_of :width, :greater_than => :minimum_weight
# end
#
- #
-
def validates_numericality_of(*attr_names)
- configuration = { :only_integer => false, :allow_nil => false }
- configuration.update(attr_names.extract_options!)
+ options = { :only_integer => false, :allow_nil => false }
+ options.update(attr_names.extract_options!)
- numericality_options = ALL_NUMERICALITY_CHECKS.keys & configuration.keys
+ numericality_options = NumericalityValidator::CHECKS.keys & options.keys
(numericality_options - [ :odd, :even ]).each do |option|
- value = configuration[option]
+ value = options[option]
raise ArgumentError, ":#{option} must be a number, a symbol or a proc" unless value.is_a?(Numeric) || value.is_a?(Proc) || value.is_a?(Symbol)
end
- validates_each(attr_names,configuration) do |record, attr_name, value|
- before_type_cast = "#{attr_name}_before_type_cast"
-
- if record.respond_to?(before_type_cast.to_sym)
- raw_value = record.send("#{attr_name}_before_type_cast") || value
- else
- raw_value = value
- end
-
- next if configuration[:allow_nil] and raw_value.nil?
-
- if configuration[:only_integer]
- unless raw_value.to_s =~ /\A[+-]?\d+\Z/
- record.errors.add(attr_name, :not_a_number, :value => raw_value, :default => configuration[:message])
- next
- end
- raw_value = raw_value.to_i
- else
- begin
- raw_value = Kernel.Float(raw_value)
- rescue ArgumentError, TypeError
- record.errors.add(attr_name, :not_a_number, :value => raw_value, :default => configuration[:message])
- next
- end
- end
-
- numericality_options.each do |option|
- case option
- when :odd, :even
- unless raw_value.to_i.method(ALL_NUMERICALITY_CHECKS[option])[]
- record.errors.add(attr_name, option, :value => raw_value, :default => configuration[:message])
- end
- else
- configuration[option] = configuration[option].call(record) if configuration[option].is_a? Proc
- configuration[option] = record.method(configuration[option]).call if configuration[option].is_a? Symbol
-
- unless raw_value.method(ALL_NUMERICALITY_CHECKS[option])[configuration[option]]
- record.errors.add(attr_name, option, :default => configuration[:message], :value => raw_value, :count => configuration[option])
- end
- end
- end
- end
+ validates_with NumericalityValidator, options.merge(:attributes => attr_names)
end
end
end