diff options
author | Edouard CHIN <edouard.chin@shopify.com> | 2019-01-22 00:18:56 +0100 |
---|---|---|
committer | Edouard CHIN <edouard.chin@shopify.com> | 2019-01-22 20:46:16 +0100 |
commit | f01e38509c442903edaf12f23749193ce1f2d1d9 (patch) | |
tree | e045f4a0a5268bec439efdca892955da26f5ef12 /activemodel/test/cases/validations | |
parent | 4f62e757caf608d30d46ee745f4f666fb8eba2a7 (diff) | |
download | rails-f01e38509c442903edaf12f23749193ce1f2d1d9.tar.gz rails-f01e38509c442903edaf12f23749193ce1f2d1d9.tar.bz2 rails-f01e38509c442903edaf12f23749193ce1f2d1d9.zip |
Fix NumericalityValidator on object responding to `to_f`:
- If you had a PORO that acted like a Numeric, the validator would
work correctly because it was previously using `Kernel.Float`
which is implicitely calling `to_f` on the passed argument.
Since rails/rails@d126c0d , we are now using `BigDecimal` which does
not implicitely call `to_f` on the argument, making the validator
fail with an underlying `TypeError` exception.
This patch replate the `is_decimal?` check with `Kernel.Float`.
Using `Kernel.Float` as argument for the BigDecimal call has two
advantages:
1. It calls `to_f` implicetely for us.
2. It's also smart enough to detect that `Kernel.Float("a")` isn't a
Numeric and will raise an error.
We don't need the `is_decimal?` check thanks to that.
Passing `Float::DIG` as second argument to `BigDecimal` is mandatory
because the precision can't be omitted when passing a Float.
`Float::DIG` is what is used internally by ruby when calling
`123.to_d`
https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/lib/bigdecimal/util.rb#L47
- Another small issue introduced in https://github.com/rails/rails/pull/34693
would now raise a TypeError because `Regexp#===` will just return
false if the passed argument isn't a string or symbol, whereas
`Regexp#match?` will.
Diffstat (limited to 'activemodel/test/cases/validations')
-rw-r--r-- | activemodel/test/cases/validations/numericality_validation_test.rb | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/activemodel/test/cases/validations/numericality_validation_test.rb b/activemodel/test/cases/validations/numericality_validation_test.rb index eb4b02df93..fcdf123062 100644 --- a/activemodel/test/cases/validations/numericality_validation_test.rb +++ b/activemodel/test/cases/validations/numericality_validation_test.rb @@ -281,6 +281,19 @@ class NumericalityValidationTest < ActiveModel::TestCase assert_predicate topic, :invalid? end + def test_validates_numericalty_with_object_acting_as_numeric + klass = Class.new do + def to_f + 123.54 + end + end + + Topic.validates_numericality_of :price + topic = Topic.new(price: klass.new) + + assert_predicate topic, :valid? + end + def test_validates_numericality_with_invalid_args assert_raise(ArgumentError) { Topic.validates_numericality_of :approved, greater_than_or_equal_to: "foo" } assert_raise(ArgumentError) { Topic.validates_numericality_of :approved, less_than_or_equal_to: "foo" } |