diff options
author | Sean Griffin <sean@thoughtbot.com> | 2014-11-30 18:24:53 -0700 |
---|---|---|
committer | Sean Griffin <sean@thoughtbot.com> | 2014-12-01 05:31:44 -0700 |
commit | 704c658531ae202715cba29d6b2ba64651f220fd (patch) | |
tree | 23d985b99313d0b41df014b8e29ea82f0f9a5799 /activemodel | |
parent | 8226bad7101fd35e774ca6d233c605c4cee2abd8 (diff) | |
download | rails-704c658531ae202715cba29d6b2ba64651f220fd.tar.gz rails-704c658531ae202715cba29d6b2ba64651f220fd.tar.bz2 rails-704c658531ae202715cba29d6b2ba64651f220fd.zip |
Ensure numericality validations work with mutation
The detection of in-place changes caused a weird unexpected issue with
numericality validations. That validator (out of necessity) works on the
`_before_type_cast` version of the attribute, since on an `:integer`
type column, a non-numeric string would type cast to 0.
However, strings are mutable, and we changed strings to ensure that the
post type cast version of the attribute was a different instance than
the before type cast version (so the mutation detection can work
properly).
Even though strings are the only mutable type for which a numericality
validation makes sense, special casing strings would feel like a strange
change to make here. Instead, we can make the assumption that for all
mutable types, we should work on the post-type-cast version of the
attribute, since all cases which would return 0 for non-numeric strings
are immutable.
Fixes #17852
Diffstat (limited to 'activemodel')
-rw-r--r-- | activemodel/lib/active_model/validations/numericality.rb | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 13d6a966c0..4ba4e3e8f7 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -23,6 +23,10 @@ module ActiveModel raw_value = record.send(before_type_cast) if record.respond_to?(before_type_cast) raw_value ||= value + if record_attribute_changed_in_place?(record, attr_name) + raw_value = value + end + return if options[:allow_nil] && raw_value.nil? unless value = parse_raw_value_as_a_number(raw_value) @@ -86,6 +90,13 @@ module ActiveModel options[:only_integer] end end + + private + + def record_attribute_changed_in_place?(record, attr_name) + record.respond_to?(:attribute_changed_in_place?) && + record.attribute_changed_in_place?(attr_name.to_s) + end end module HelperMethods |