From 9e25e0e1735f2ccca69679243aa8cf0885104164 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Tue, 6 Oct 2015 08:51:14 -0600 Subject: [PATCH] Implement equality comparison on `AttributeSet` and friends Any gems or libraries which do work with serialization or YAML will ultimately need to compare these objects (albeit indirectly) to ensure correctness. These will likely never get used internally (as they're slow), but we should still expose them for others. --- .../lib/active_record/attribute_set.rb | 4 +++ .../active_record/attribute_set/builder.rb | 30 ++++++++++++------- activerecord/test/cases/attribute_set_test.rb | 10 +++++++ 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/activerecord/lib/active_record/attribute_set.rb b/activerecord/lib/active_record/attribute_set.rb index 026b3cf014..be581ac2a9 100644 --- a/activerecord/lib/active_record/attribute_set.rb +++ b/activerecord/lib/active_record/attribute_set.rb @@ -91,6 +91,10 @@ module ActiveRecord AttributeSet.new(new_attributes) end + def ==(other) + attributes == other.attributes + end + protected attr_reader :attributes diff --git a/activerecord/lib/active_record/attribute_set/builder.rb b/activerecord/lib/active_record/attribute_set/builder.rb index f974b7a876..3bd7c7997b 100644 --- a/activerecord/lib/active_record/attribute_set/builder.rb +++ b/activerecord/lib/active_record/attribute_set/builder.rb @@ -68,10 +68,29 @@ module ActiveRecord end end + def ==(other) + if other.is_a?(LazyAttributeHash) + materialize == other.materialize + else + materialize == other + end + end + protected attr_reader :types, :values, :additional_types, :delegate_hash + def materialize + unless @materialized + values.each_key { |key| self[key] } + types.each_key { |key| self[key] } + unless frozen? + @materialized = true + end + end + delegate_hash + end + private def assign_default_value(name) @@ -85,16 +104,5 @@ module ActiveRecord delegate_hash[name] = Attribute.uninitialized(name, type) end end - - def materialize - unless @materialized - values.each_key { |key| self[key] } - types.each_key { |key| self[key] } - unless frozen? - @materialized = true - end - end - delegate_hash - end end end diff --git a/activerecord/test/cases/attribute_set_test.rb b/activerecord/test/cases/attribute_set_test.rb index 5a0e463a48..7a24b85a36 100644 --- a/activerecord/test/cases/attribute_set_test.rb +++ b/activerecord/test/cases/attribute_set_test.rb @@ -239,5 +239,15 @@ module ActiveRecord assert_equal 2, new_attributes.fetch_value(:foo) assert_equal 3, new_attributes.fetch_value(:bar) end + + test "comparison for equality is correctly implemented" do + builder = AttributeSet::Builder.new(foo: Type::Integer.new, bar: Type::Integer.new) + attributes = builder.build_from_database(foo: "1", bar: "2") + attributes2 = builder.build_from_database(foo: "1", bar: "2") + attributes3 = builder.build_from_database(foo: "2", bar: "2") + + assert_equal attributes, attributes2 + assert_not_equal attributes2, attributes3 + end end end