3 Plugins for Safer ActiveRecord Deletions
It's a fairly common requirement for Rails applications: allow the user to delete data but provide some sort of safety valve so that it can be restored. After all, users make mistakes, and one mistaken deletion can ruin your whole day. Although ActiveRecord itself doesn't directly address this scenario, Rails developers have the choice of several plugins to handle it.
acts_as_paranoid - flags items as deleted in situ
The grandfather of them all is acts_as_paranoid. acts_as_paranoid takes the approach of adding a deleted_at attribute to your model, and overriding ActiveRecord#destroy to set that attribute instead of actually deleting the record. It then overrides ActiveRecord#find to hide the pseudo-deleted records. Unfortunately this code is a little long in the tooth, and may not play nicely with recent Rails releases.
acts_as_soft_deletable - moves deleted items to a different table
acts_as_soft_deletable takes a different approach. Instead of keeping the records in the table and flagging them (which ends up requiring quite a bit of messing around with ActiveRecord internals), it wraps the destroy method and uses it to move rows to a special table instead. On the plus side, this is less intrusive, and may result in better performance when dealing with the "real" data table, since it won't be littered with deleted records. On the minus side, it commits you to maintaining two tables for each entity, and keeping them in sync.
acts_as_trashable - serializes deleted data to a "trash" table
You can see a third approach to this problem in acts_as_trashable. This one maintains a single "trash" table into which it serializes any data you delete (at least, for models that are declared to be trashable). The nicest feature here is that the serialization includes any deleted associated child records. acts_as_trashable also includes support for taking out the trash to reduce the size of the trash table.
Depending on your version of Rails, you may find rough edges with any of these three approaches. Best bet: decide which approach feels best for your own particular data needs, and then carefully test before deploying.
Support from: 1st Easy offers UK Rails hosting (dedicated and shared) running Phusion Passenger (mod_rails) and LAMP stack. If you want to get to know us first, or simply want to evaluate the performance of your Rails applications running on Passenger, we'll arrange a trial hosting account for you (full technical support included!)
December 6th, 2008 at 3:04 am
Thanks for the post! I've been looking for a neat little write-up like this.
-- Josh
December 6th, 2008 at 6:09 am
It would be nice if you can tell the reason why acts_as_paranoid won't work well with latest Rails.
December 6th, 2008 at 7:43 am
Thanks for the comparison, i always wondered if there are other aproaches out there.
Imo soft-deleteable is superior to paranoid, the little extra migration overhead is worth it...
Trashable seems nice, but when the user is too old recovery could get hard (rows missing/validations failing) but keeping the deleted childs seems promissing...
December 6th, 2008 at 10:58 am
Thanks for the write-up! However, could you (or anyone else who has experience with these plugins) tell me something about the ease of restoring data from the three aforementioned mechanisms?
Keeping a backup of AR-data is one thing, but how do you restore this data when needed and how much effort does it take?
December 7th, 2008 at 7:54 am
1 and 2 should be easy, but 3 could get hard when your data is out of date...
December 12th, 2008 at 7:12 pm
@marcel: just use recover! class method with acts_as_paranoid
December 26th, 2008 at 1:13 am
Acts as paranoid doesn't work properly as of Rails 2.1.2 (the last known working version that I have in production is with Rails 2.1.0)
The problem in 2.1.2 is that something must have changed in the rails code to cause deleted items to appear again in associations. I'm in the process of ripping out Acts as Paranoid now. It should not be used at all and should probably be deprecated entirely with strong warnings to avoid use.