Add only_numeric option to numericality validator

This commit is contained in:
Orhan Toy 2021-12-16 22:15:01 +01:00
parent 4607108f91
commit 318d6905e2
2 changed files with 26 additions and 3 deletions

View File

@ -11,7 +11,7 @@ module ActiveModel
RANGE_CHECKS = { in: :in? }
NUMBER_CHECKS = { odd: :odd?, even: :even? }
RESERVED_OPTIONS = COMPARE_CHECKS.keys + NUMBER_CHECKS.keys + RANGE_CHECKS.keys + [:only_integer]
RESERVED_OPTIONS = COMPARE_CHECKS.keys + NUMBER_CHECKS.keys + RANGE_CHECKS.keys + [:only_integer, :only_numeric]
INTEGER_REGEX = /\A[+-]?\d+\z/
@ -90,6 +90,10 @@ module ActiveModel
end
def is_number?(raw_value, precision, scale)
if options[:only_numeric] && !raw_value.is_a?(Numeric)
return false
end
!parse_as_number(raw_value, precision, scale).nil?
rescue ArgumentError, TypeError
false
@ -162,6 +166,9 @@ module ActiveModel
# * <tt>:message</tt> - A custom error message (default is: "is not a number").
# * <tt>:only_integer</tt> - Specifies whether the value has to be an
# integer (default is +false+).
# * <tt>:only_numeric</tt> - Specifies whether the value has to be an
# instance of Numeric (default is +false+). The default behavior is to
# attempt parsing the value if it is a String.
# * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+ (default is
# +false+). Notice that for Integer and Float columns empty strings are
# converted to +nil+.

View File

@ -19,8 +19,10 @@ class NumericalityValidationTest < ActiveModel::TestCase
BIGDECIMAL_STRINGS = %w(12345678901234567890.1234567890) # 30 significant digits
FLOAT_STRINGS = %w(0.0 +0.0 -0.0 10.0 10.5 -10.5 -0.0001 -090.1 90.1e1 -90.1e5 -90.1e-5 90e-5)
INTEGER_STRINGS = %w(0 +0 -0 10 +10 -10 0090 -090)
FLOATS = [0.0, 10.0, 10.5, -10.5, -0.0001] + FLOAT_STRINGS
INTEGERS = [0, 10, -10] + INTEGER_STRINGS
NUMERIC_FLOATS = [0.0, 10.0, 10.5, -10.5, -0.0001]
NUMERIC_INTEGERS = [0, 10, -10]
FLOATS = NUMERIC_FLOATS + FLOAT_STRINGS
INTEGERS = NUMERIC_INTEGERS + INTEGER_STRINGS
BIGDECIMAL = BIGDECIMAL_STRINGS.collect! { |bd| BigDecimal(bd) }
JUNK = ["not a number", "42 not a number", "0xdeadbeef", "-0xdeadbeef", "+0xdeadbeef", "0xinvalidhex", "0Xdeadbeef", "00-1", "--3", "+-3", "+3-1", "-+019.0", "12.12.13.12", "123\nnot a number"]
INFINITY = [1.0 / 0.0]
@ -74,6 +76,20 @@ class NumericalityValidationTest < ActiveModel::TestCase
assert_valid_values(FLOATS + INTEGERS + BIGDECIMAL + INFINITY)
end
def test_validates_numericality_of_with_numeric_only
Topic.validates_numericality_of :approved, only_numeric: true
assert_invalid_values(NIL + BLANK + JUNK + FLOAT_STRINGS + INTEGER_STRINGS)
assert_valid_values(NUMERIC_FLOATS + NUMERIC_INTEGERS + BIGDECIMAL + INFINITY)
end
def test_validates_numericality_of_with_numeric_only_and_nil_allowed
Topic.validates_numericality_of :approved, only_numeric: true, allow_nil: true
assert_invalid_values(JUNK + BLANK + FLOAT_STRINGS + INTEGER_STRINGS)
assert_valid_values(NIL + NUMERIC_FLOATS + NUMERIC_INTEGERS + BIGDECIMAL + INFINITY)
end
def test_validates_numericality_with_greater_than
Topic.validates_numericality_of :approved, greater_than: 10