Change Numericaly validator to use round

f72f743 introduces truncate(scale) in the Numericality validator.
This behaviour conflicts with AR decimal type conversion,
which uses round(scale) instead.

Changes the Numericality validator in order to use
round(scale) for consistency.
This commit is contained in:
Jacopo 2021-01-05 18:08:01 +01:00
parent 2afc9059c9
commit 6657e3428b
3 changed files with 33 additions and 4 deletions

View File

@ -71,6 +71,8 @@ module ActiveModel
raw_value if raw_value.is_a?(Range)
elsif raw_value.is_a?(Float)
parse_float(raw_value, precision, scale)
elsif raw_value.is_a?(BigDecimal)
round(raw_value, scale)
elsif raw_value.is_a?(Numeric)
raw_value
elsif is_integer?(raw_value)
@ -81,7 +83,11 @@ module ActiveModel
end
def parse_float(raw_value, precision, scale)
(scale ? raw_value.truncate(scale) : raw_value).to_d(precision)
round(raw_value, scale).to_d(precision)
end
def round(raw_value, scale)
scale ? raw_value.round(scale) : raw_value
end
def is_number?(raw_value, precision, scale)

View File

@ -103,6 +103,21 @@ class NumericalityValidationTest < ActiveRecord::TestCase
assert_not_predicate subject, :valid?
end
def test_virtual_attribute_with_precision_and_scale
model_class.attribute(:virtual_decimal_number, :decimal, precision: 4, scale: 2)
model_class.validates_numericality_of(
:virtual_decimal_number, less_than_or_equal_to: 99.99
)
subject = model_class.new(virtual_decimal_number: 99.994)
assert_equal 99.99.to_d(4), subject.virtual_decimal_number
assert_predicate subject, :valid?
subject = model_class.new(virtual_decimal_number: 99.999)
assert_equal 100.00.to_d(4), subject.virtual_decimal_number
assert_not_predicate subject, :valid?
end
def test_aliased_attribute
model_class.validates_numericality_of(:new_bank_balance, greater_or_equal_than: 0)

View File

@ -187,9 +187,17 @@ class ValidationsTest < ActiveRecord::TestCase
validates_numericality_of :wibble, greater_than_or_equal_to: BigDecimal("97.18")
end
assert_not_predicate klass.new(wibble: "97.179"), :valid?
assert_not_predicate klass.new(wibble: 97.179), :valid?
assert_not_predicate klass.new(wibble: BigDecimal("97.179")), :valid?
["97.179", 97.179, BigDecimal("97.179")].each do |raw_value|
subject = klass.new(wibble: raw_value)
assert_equal 97.18.to_d(4), subject.wibble
assert_predicate subject, :valid?
end
["97.174", 97.174, BigDecimal("97.174")].each do |raw_value|
subject = klass.new(wibble: raw_value)
assert_equal 97.17.to_d(4), subject.wibble
assert_not_predicate subject, :valid?
end
end
def test_numericality_validator_wont_be_affected_by_custom_getter