Skip to content

Commit

Permalink
Merge pull request #41019 from intrip/40902-fix-numericality-validator
Browse files Browse the repository at this point in the history
Use round(scale) in  ActiveModel NumericalityValidator
  • Loading branch information
kamipo committed Jan 14, 2021
1 parent 07acc85 commit f10dfa7
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
8 changes: 7 additions & 1 deletion activemodel/lib/active_model/validations/numericality.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ def validate_each(record, attr_name, value, precision: Float::DIG, scale: nil)
def parse_as_number(raw_value, precision, scale)
if 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)
Expand All @@ -74,7 +76,11 @@ def parse_as_number(raw_value, precision, scale)
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,25 @@ def test_virtual_attribute_with_scale
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
)

["99.994", 99.994, BigDecimal("99.994")].each do |raw_value|
subject = model_class.new(virtual_decimal_number: raw_value)
assert_equal BigDecimal("99.99"), subject.virtual_decimal_number
assert_predicate subject, :valid?
end

["99.999", 99.999, BigDecimal("99.999")].each do |raw_value|
subject = model_class.new(virtual_decimal_number: raw_value)
assert_equal BigDecimal("100.00"), subject.virtual_decimal_number
assert_not_predicate subject, :valid?
end
end

def test_aliased_attribute
model_class.validates_numericality_of(:new_bank_balance, greater_or_equal_than: 0)

Expand Down
14 changes: 11 additions & 3 deletions activerecord/test/cases/validations_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,17 @@ def self.model_name
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 BigDecimal("97.18"), 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 BigDecimal("97.17"), subject.wibble
assert_not_predicate subject, :valid?
end
end

def test_numericality_validator_wont_be_affected_by_custom_getter
Expand Down

0 comments on commit f10dfa7

Please sign in to comment.