Sorry this page looks weird. It was automatically migrated from my old blog, which had a different layout and different CSS.

PaperTrail and Rails 3

PaperTrail is a gem which lets you easily track changes to your ActiveRecord models' data. Until yesterday the same code ran on both Rails 2.3 and Rails 3, but now I have a branch for each.

For Rails 3, use the master branch and the v2.x tags.

For Rails 2.3, use the rails2 branch and the v1.x tags.

Rails 2.3 versus Rails 3

The only non-obvious difference between Rails 2.3 and Rails 3 is when a paper-trailed model is destroyed. In Rails 2.3 I could use versions.create in the after_destroy hook to add a version for the destroyed record.

# Rails 2.3
versions.create merge_metadata(:event     => 'destroy',
                               :object    => object_to_string(item_before_change),
                               :whodunnit => PaperTrail.whodunnit)

But Rails 3 raises an exception because the parent has already been destroyed. So instead we have to do this:

# Rails 3
Version.create merge_metadata(:item      => self,
                              :event     => 'destroy',
                              :object    => object_to_string(item_before_change),
                              :whodunnit => PaperTrail.whodunnit)

Related is the fact that the new version is not available in the versions proxy:

>> book = Book.find 42
>> book.versions.length   # => 3 (for example)
>> book.destroy
>> book.versions.length   # => 3 not 4

This is explained in a comment at the top of the AssociationCollection class, though I couldn’t figure out how to get a destroyed object’s versions proxy to return the correct length.

Enginex

I used José Valim’s excellent Enginex tool to set up the load path to work with a test Rails app. This is the second time I’ve used it – the first was for Quo Vadis – and it saves a lot of time. Paper Trail’s tests now run against a proper app which makes them more realistic.

Andrew Stewart • 9 February 2011 • RailsPaperTrail
You can reach me by email or on Twitter.