diff options
author | Sean Griffin <sean@seantheprogrammer.com> | 2016-05-12 09:06:29 -0400 |
---|---|---|
committer | Sean Griffin <sean@seantheprogrammer.com> | 2016-05-12 09:09:47 -0400 |
commit | 6007e584d824225e51f47ba0684d48ea3eb8f518 (patch) | |
tree | d75d636ca8c927b6c4502a6bd06725a04d0a2ad2 /activerecord/test | |
parent | 548c1d6e8b819ca4e02e6218b67107c580ee65f2 (diff) | |
download | rails-6007e584d824225e51f47ba0684d48ea3eb8f518.tar.gz rails-6007e584d824225e51f47ba0684d48ea3eb8f518.tar.bz2 rails-6007e584d824225e51f47ba0684d48ea3eb8f518.zip |
Fix false positive mutation detection when JSON is used with serialize
When looking for mutation, we compare the serialized version of the
value to the before_type_cast form. `Type::Serialized` was breaking this
contract by passing the already serialized attribute to the subtype's
mutation detection. This never manifested previously, as all mutable
subtypes either didn't do anything in their `serialize` method, or had a
way to detect double serialization (e.g. `is_a?(String)`). However, now
that JSON types can handle string primitives, we need to avoid double
serialization.
Fixes #24993.
Diffstat (limited to 'activerecord/test')
-rw-r--r-- | activerecord/test/cases/serialized_attribute_test.rb | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb index 6056156698..846be857d0 100644 --- a/activerecord/test/cases/serialized_attribute_test.rb +++ b/activerecord/test/cases/serialized_attribute_test.rb @@ -295,4 +295,37 @@ class SerializedAttributeTest < ActiveRecord::TestCase topic.update_attribute :content, nil assert_equal [topic], Topic.where(content: nil) end + + def test_mutation_detection_does_not_double_serialize + coder = Object.new + def coder.dump(value) + return if value.nil? + value + " encoded" + end + def coder.load(value) + return if value.nil? + value.gsub(" encoded", "") + end + type = Class.new(ActiveModel::Type::Value) do + include ActiveModel::Type::Helpers::Mutable + + def serialize(value) + return if value.nil? + value + " serialized" + end + + def deserialize(value) + return if value.nil? + value.gsub(" serialized", "") + end + end.new + model = Class.new(Topic) do + attribute :foo, type + serialize :foo, coder + end + + topic = model.create!(foo: "bar") + topic.foo + refute topic.changed? + end end |