aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Moss <me@jonathanmoss.me>2016-12-30 18:43:04 -0500
committerJon Moss <me@jonathanmoss.me>2017-01-03 16:07:47 -0500
commit8ded825bc29338d1a2ae7c3a2119cfa301008f85 (patch)
treec9d5d943dd37d2273405d3c9cbd3d3278a04c523
parent769b25af588d87e4570c6b454990118ab432a3aa (diff)
downloadrails-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
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb8
-rw-r--r--activerecord/test/cases/adapters/postgresql/hstore_test.rb19
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