Skip to content

Commit 6383577

Browse files
authored
Merge pull request rails#41019 from intrip/40902-fix-numericality-validator
Use round(scale) in ActiveModel NumericalityValidator
2 parents 7659dd0 + 6657e34 commit 6383577

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

activemodel/lib/active_model/validations/numericality.rb

+7-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ def parse_as_number(raw_value, precision, scale, option = nil)
7171
raw_value if raw_value.is_a?(Range)
7272
elsif raw_value.is_a?(Float)
7373
parse_float(raw_value, precision, scale)
74+
elsif raw_value.is_a?(BigDecimal)
75+
round(raw_value, scale)
7476
elsif raw_value.is_a?(Numeric)
7577
raw_value
7678
elsif is_integer?(raw_value)
@@ -81,7 +83,11 @@ def parse_as_number(raw_value, precision, scale, option = nil)
8183
end
8284

8385
def parse_float(raw_value, precision, scale)
84-
(scale ? raw_value.truncate(scale) : raw_value).to_d(precision)
86+
round(raw_value, scale).to_d(precision)
87+
end
88+
89+
def round(raw_value, scale)
90+
scale ? raw_value.round(scale) : raw_value
8591
end
8692

8793
def is_number?(raw_value, precision, scale)

activerecord/test/cases/validations/numericality_validation_test.rb

+15
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,21 @@ def test_virtual_attribute_with_scale
103103
assert_not_predicate subject, :valid?
104104
end
105105

106+
def test_virtual_attribute_with_precision_and_scale
107+
model_class.attribute(:virtual_decimal_number, :decimal, precision: 4, scale: 2)
108+
model_class.validates_numericality_of(
109+
:virtual_decimal_number, less_than_or_equal_to: 99.99
110+
)
111+
112+
subject = model_class.new(virtual_decimal_number: 99.994)
113+
assert_equal 99.99.to_d(4), subject.virtual_decimal_number
114+
assert_predicate subject, :valid?
115+
116+
subject = model_class.new(virtual_decimal_number: 99.999)
117+
assert_equal 100.00.to_d(4), subject.virtual_decimal_number
118+
assert_not_predicate subject, :valid?
119+
end
120+
106121
def test_aliased_attribute
107122
model_class.validates_numericality_of(:new_bank_balance, greater_or_equal_than: 0)
108123

activerecord/test/cases/validations_test.rb

+11-3
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,17 @@ def self.model_name
187187
validates_numericality_of :wibble, greater_than_or_equal_to: BigDecimal("97.18")
188188
end
189189

190-
assert_not_predicate klass.new(wibble: "97.179"), :valid?
191-
assert_not_predicate klass.new(wibble: 97.179), :valid?
192-
assert_not_predicate klass.new(wibble: BigDecimal("97.179")), :valid?
190+
["97.179", 97.179, BigDecimal("97.179")].each do |raw_value|
191+
subject = klass.new(wibble: raw_value)
192+
assert_equal 97.18.to_d(4), subject.wibble
193+
assert_predicate subject, :valid?
194+
end
195+
196+
["97.174", 97.174, BigDecimal("97.174")].each do |raw_value|
197+
subject = klass.new(wibble: raw_value)
198+
assert_equal 97.17.to_d(4), subject.wibble
199+
assert_not_predicate subject, :valid?
200+
end
193201
end
194202

195203
def test_numericality_validator_wont_be_affected_by_custom_getter

0 commit comments

Comments
 (0)