Skip excess cloning of JSONized `object_changes` (#1189)

* Skip excess cloning of JSONized `object_changes`

* Suggestions for PR 1189, to be squashed
This commit is contained in:
Sergey Tokarenko 2019-03-13 20:47:23 +03:00 committed by Jared Beck
parent ccf5e1e4d5
commit ca4f532623
3 changed files with 18 additions and 2 deletions

View File

@ -238,9 +238,14 @@ module PaperTrail
# serialization here, using `PaperTrail.serializer`.
#
# @api private
# @param changes HashWithIndifferentAccess
def recordable_object_changes(changes)
if PaperTrail.config.object_changes_adapter&.respond_to?(:diff)
changes = PaperTrail.config.object_changes_adapter.diff(changes)
# We'd like to avoid the `to_hash` here, because it increases memory
# usage, but that would be a breaking change because
# `object_changes_adapter` expects a plain `Hash`, not a
# `HashWithIndifferentAccess`.
changes = PaperTrail.config.object_changes_adapter.diff(changes.to_hash)
end
if @record.class.paper_trail.version_class.object_changes_col_is_json?
@ -285,7 +290,10 @@ module PaperTrail
AttributeSerializers::ObjectChangesAttribute.
new(@record.class).
serialize(changes)
changes.to_hash
# We'd like to convert this `HashWithIndifferentAccess` to a plain
# `Hash`, but we don't, to save memory.
changes
end
end
end

View File

@ -12,7 +12,12 @@ module PaperTrail
::YAML.load string
end
# @param object (Hash | HashWithIndifferentAccess) - Coming from
# `recordable_object` `object` will be a plain `Hash`. However, due to
# recent [memory optimizations](https://git.io/fjeYv), when coming from
# `recordable_object_changes`, it will be a `HashWithIndifferentAccess`.
def dump(object)
object = object.to_hash if object.is_a?(HashWithIndifferentAccess)
::YAML.dump object
end

View File

@ -15,6 +15,7 @@ module PaperTrail
float: 4.2
}
}
let(:hash_with_indifferent_access) { HashWithIndifferentAccess.new(hash) }
describe ".load" do
it "deserializes YAML to Ruby" do
@ -26,6 +27,8 @@ module PaperTrail
describe ".dump" do
it "serializes Ruby to YAML" do
expect(described_class.dump(hash)).to eq(hash.to_yaml)
expect(described_class.dump(hash_with_indifferent_access)).
to eq(hash.stringify_keys.to_yaml)
expect(described_class.dump(array)).to eq(array.to_yaml)
end
end