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