diff options
author | Jon Moss <me@jonathanmoss.me> | 2016-12-30 18:43:04 -0500 |
---|---|---|
committer | Jon Moss <me@jonathanmoss.me> | 2017-01-03 16:07:47 -0500 |
commit | 8ded825bc29338d1a2ae7c3a2119cfa301008f85 (patch) | |
tree | c9d5d943dd37d2273405d3c9cbd3d3278a04c523 /activerecord | |
parent | 769b25af588d87e4570c6b454990118ab432a3aa (diff) | |
download | rails-8ded825bc29338d1a2ae7c3a2119cfa301008f85.tar.gz rails-8ded825bc29338d1a2ae7c3a2119cfa301008f85.tar.bz2 rails-8ded825bc29338d1a2ae7c3a2119cfa301008f85.zip |
Compare deserialized values for `PostgreSQL::OID::Hstore` types
Per the regression commit below, the commit changes the behavior of
`#changed?`to consult the `#changed_in_place?` method on `Type::Value` classes.
Per this change, `PostgreSQL::OID::Hstore` needs to override this method
in order to compare the deserialized forms of the two arguments. In
Ruby, two hashes are considered equal even if their key order is
different. This commit helps to bring that behavior to `Hstore` values.
Fixes regression introduced by 8e633e505880755e7e366ccec2210bbe2b5436e7
Fixes #27502
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG.md | 7 | ||||
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb | 8 | ||||
-rw-r--r-- | activerecord/test/cases/adapters/postgresql/hstore_test.rb | 19 |
3 files changed, 34 insertions, 0 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 00d1a7a623..743a38b087 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,10 @@ +* Compare deserialized values for `PostgreSQL::OID::Hstore` types when + calling `ActiveRecord::Dirty#changed_in_place?` + + Fixes #27502. + + *Jon Moss* + * Raise `ArgumentError` when passing an `ActiveRecord::Base` instance to `.find` and `.exists?`. diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb index d629ebca91..49dd4fc73f 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb @@ -35,6 +35,14 @@ module ActiveRecord ActiveRecord::Store::StringKeyedHashAccessor end + # Will compare the Hash equivalents of +raw_old_value+ and +new_value+. + # By comparing hashes, this avoids an edge case where the order of + # the keys change between the two hashes, and they would not be marked + # as equal. + def changed_in_place?(raw_old_value, new_value) + deserialize(raw_old_value) != new_value + end + private HstorePair = begin diff --git a/activerecord/test/cases/adapters/postgresql/hstore_test.rb b/activerecord/test/cases/adapters/postgresql/hstore_test.rb index 1f35300739..f9cce10fb8 100644 --- a/activerecord/test/cases/adapters/postgresql/hstore_test.rb +++ b/activerecord/test/cases/adapters/postgresql/hstore_test.rb @@ -171,6 +171,25 @@ if ActiveRecord::Base.connection.supports_extensions? assert_not hstore.changed? end + def test_dirty_from_user_equal + settings = { "alongkey" => "anything", "key" => "value" } + hstore = Hstore.create!(settings: settings) + + hstore.settings = { "key" => "value", "alongkey" => "anything" } + assert_equal settings, hstore.settings + refute hstore.changed? + end + + def test_hstore_dirty_from_database_equal + settings = { "alongkey" => "anything", "key" => "value" } + hstore = Hstore.create!(settings: settings) + hstore.reload + + assert_equal settings, hstore.settings + hstore.settings = settings + refute hstore.changed? + end + def test_gen1 assert_equal('" "=>""', @type.serialize(" " => "")) end |