lib/active_model/validations/numericality.rb in activemodel-5.2.2.1 vs lib/active_model/validations/numericality.rb in activemodel-5.2.3.rc1
- old
+ new
@@ -1,16 +1,20 @@
# frozen_string_literal: true
+require "bigdecimal/util"
+
module ActiveModel
module Validations
class NumericalityValidator < EachValidator # :nodoc:
CHECKS = { greater_than: :>, greater_than_or_equal_to: :>=,
equal_to: :==, less_than: :<, less_than_or_equal_to: :<=,
odd: :odd?, even: :even?, other_than: :!= }.freeze
RESERVED_OPTIONS = CHECKS.keys + [:only_integer]
+ INTEGER_REGEX = /\A[+-]?\d+\z/
+
def check_validity!
keys = CHECKS.keys - [:odd, :even]
options.slice(*keys).each do |option, value|
unless value.is_a?(Numeric) || value.is_a?(Proc) || value.is_a?(Symbol)
raise ArgumentError, ":#{option} must be a number, a symbol or a proc"
@@ -47,15 +51,11 @@
if allow_only_integer?(record) && !is_integer?(raw_value)
record.errors.add(attr_name, :not_an_integer, filtered_options(raw_value))
return
end
- if raw_value.is_a?(Numeric)
- value = raw_value
- else
- value = parse_raw_value_as_a_number(raw_value)
- end
+ value = parse_as_number(raw_value)
options.slice(*CHECKS.keys).each do |option, option_value|
case option
when :odd, :even
unless value.to_i.send(CHECKS[option])
@@ -67,35 +67,44 @@
option_value = option_value.call(record)
when Symbol
option_value = record.send(option_value)
end
+ option_value = parse_as_number(option_value)
+
unless value.send(CHECKS[option], option_value)
record.errors.add(attr_name, option, filtered_options(value).merge!(count: option_value))
end
end
end
end
private
def is_number?(raw_value)
- !parse_raw_value_as_a_number(raw_value).nil?
+ !parse_as_number(raw_value).nil?
rescue ArgumentError, TypeError
false
end
- def parse_raw_value_as_a_number(raw_value)
- return raw_value.to_i if is_integer?(raw_value)
- Kernel.Float(raw_value) unless is_hexadecimal_literal?(raw_value)
+ def parse_as_number(raw_value)
+ if raw_value.is_a?(Float)
+ raw_value.to_d
+ elsif raw_value.is_a?(Numeric)
+ raw_value
+ elsif is_integer?(raw_value)
+ raw_value.to_i
+ elsif !is_hexadecimal_literal?(raw_value)
+ Kernel.Float(raw_value).to_d
+ end
end
def is_integer?(raw_value)
- /\A[+-]?\d+\z/ === raw_value.to_s
+ INTEGER_REGEX === raw_value.to_s
end
def is_hexadecimal_literal?(raw_value)
- /\A0[xX]/ === raw_value
+ /\A0[xX]/ === raw_value.to_s
end
def filtered_options(value)
filtered = options.except(*RESERVED_OPTIONS)
filtered[:value] = value