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.
This commit is contained in:
Sean Griffin 2015-10-06 08:51:14 -06:00
parent 7a96e629ef
commit 9e25e0e173
3 changed files with 33 additions and 11 deletions

View File

@ -91,6 +91,10 @@ module ActiveRecord
AttributeSet.new(new_attributes)
end
def ==(other)
attributes == other.attributes
end
protected
attr_reader :attributes

View File

@ -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

View File

@ -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