Skip to content

Commit

Permalink
track changes on destroy
Browse files Browse the repository at this point in the history
this involved refactoring the internal serialization code so it'd be possible to run it on non-Rails-provided changes
  • Loading branch information
seanlinsley committed Aug 13, 2018
1 parent 3f9b5be commit c33661e
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 15 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ recommendations of [keepachangelog.com](http://keepachangelog.com/).
- [#1099](/~https://github.com/paper-trail-gem/paper_trail/issues/1099) -
Ability to save ~50% storage space by making the `object` column optional.
Note that this disables `reify` and `where_object`.
- `object_changes` is now populated on destroy in order to make
`where_object_changes` usable when you've dropped the `object` column.
See the issue for a backport migration.

### Fixed

Expand Down
23 changes: 17 additions & 6 deletions lib/paper_trail/events/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,25 @@ def changed_in_latest_version
end

# @api private
def changes
notable_changes = changes_in_latest_version.delete_if { |k, _v|
!notably_changed.include?(k)
}
def prepare_object_changes(changes)
changes = serialize_object_changes(changes)
changes = recordable_object_changes(changes)
changes
end

# @api private
def serialize_object_changes(changes)
AttributeSerializers::ObjectChangesAttribute.
new(@record.class).
serialize(notable_changes)
notable_changes.to_hash
serialize(changes)
changes.to_hash
end

# @api private
def notable_changes
changes_in_latest_version.delete_if { |k, _v|
!notably_changed.include?(k)
}
end

# Rails 5.1 changed the API of `ActiveRecord::Dirty`. See
Expand Down
3 changes: 2 additions & 1 deletion lib/paper_trail/events/create.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ def data
data[:created_at] = @record.updated_at
end
if record_object_changes? && changed_notably?
data[:object_changes] = recordable_object_changes(changes)
changes = notable_changes
data[:object_changes] = prepare_object_changes(changes)
end
merge_metadata_into(data)
end
Expand Down
5 changes: 5 additions & 0 deletions lib/paper_trail/events/destroy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ def data
if record_object?
data[:object] = recordable_object(false)
end
if record_object_changes?
# Rails' implementation returns nothing on destroy :/
changes = @record.attributes.map { |attr, value| [attr, [value, nil]] }.to_h
data[:object_changes] = prepare_object_changes(changes)
end
merge_metadata_into(data)
end
end
Expand Down
5 changes: 3 additions & 2 deletions lib/paper_trail/events/update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Update < Base
def initialize(record, in_after_callback, is_touch, force_changes)
super(record, in_after_callback)
@is_touch = is_touch
@changes = force_changes.nil? ? changes : force_changes
@force_changes = force_changes
end

# Return attributes of nascent `Version` record.
Expand All @@ -35,7 +35,8 @@ def data
data[:object] = recordable_object(@is_touch)
end
if record_object_changes?
data[:object_changes] = recordable_object_changes(@changes)
changes = @force_changes.nil? ? notable_changes : @force_changes
data[:object_changes] = prepare_object_changes(changes)
end
merge_metadata_into(data)
end
Expand Down
19 changes: 13 additions & 6 deletions spec/paper_trail/model_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,18 @@
expect(widget.versions.last.item).to be_nil
end

it "not have changes" do
widget = Widget.create(name: "Henry")
widget.update_attributes(name: "Harry")
widget.destroy
expect(widget.versions.last.changeset).to eq({})
it "has changes" do
book = Book.create! title: "A"
changes = YAML.load book.versions.last.attributes["object_changes"]
expect(changes).to eq("id" => [nil, book.id], "title" => [nil, "A"])

book.update! title: "B"
changes = YAML.load book.versions.last.attributes["object_changes"]
expect(changes).to eq("title" => %w[A B])

book.destroy
changes = YAML.load book.versions.last.attributes["object_changes"]
expect(changes).to eq("id" => [book.id, nil], "title" => ["B", nil])
end
end
end
Expand Down Expand Up @@ -907,7 +914,7 @@
version = song.versions.last.attributes
expect(version).not_to include "object"
expect(version["event"]).to eq "destroy"
expect(version["object_changes"]).to eq nil
expect(version["object_changes"]).to start_with("---")
end

it "reify doesn't work" do
Expand Down

0 comments on commit c33661e

Please sign in to comment.