From d110b7b87743c2569b6834cc42f67d733abc8931 Mon Sep 17 00:00:00 2001 From: Will Jessop Date: Sat, 10 Aug 2019 23:37:37 +0100 Subject: [PATCH] Serialize symbols to strings in ImmutableString serialize method Symbols serialize to strings when persisted: model.some_string = :foo model.save! # "foo" is persisted This PR updates the immutable string class to serialize symbols to strings to mirror this behavior as ActiveModel::Attribute calls this serialize method to determine the return value for changed_in_place? Prior to this change this code would report that "something" had changed: comment = Comment.create! # (has a string "something" field) comment.update_column :something, :anything # persists "anything" to the "something" field of the comments table comment.something # or comment.attributes comment.something_change # will be ["anything", "anything"], note these are `to` and `from` values, but are identical After this PR the comment.something_change will return nil for this situation. Fixes #36463 --- activemodel/lib/active_model/type/immutable_string.rb | 2 +- activerecord/test/cases/dirty_test.rb | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/activemodel/lib/active_model/type/immutable_string.rb b/activemodel/lib/active_model/type/immutable_string.rb index 18e12c54d1..44de995e58 100644 --- a/activemodel/lib/active_model/type/immutable_string.rb +++ b/activemodel/lib/active_model/type/immutable_string.rb @@ -9,7 +9,7 @@ module ActiveModel def serialize(value) case value - when ::Numeric, ActiveSupport::Duration then value.to_s + when ::Numeric, ::Symbol, ActiveSupport::Duration then value.to_s when true then "t" when false then "f" else super diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index 38baf0509c..3f7d90175e 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -326,6 +326,13 @@ class DirtyTest < ActiveRecord::TestCase assert_not_predicate topic, :approved_changed? end + def test_string_attribute_should_compare_with_typecast_symbol_after_update + pirate = Pirate.create!(catchphrase: :foo) + pirate.update_column :catchphrase, :foo + pirate.catchphrase + assert_not_predicate pirate, :catchphrase_changed? + end + def test_partial_update pirate = Pirate.new(catchphrase: "foo") old_updated_on = 1.hour.ago.beginning_of_day