Embracing your paranoia with acts_as_paranoid
According to their RDoc, “Overrides some basic methods for the current model so that calling destroy sets a ‘deleted_at’ field to the current timestamp. ActiveRecord is required.”
There doesn’t seem to be really good up-to-date documentation on how to actually use it though. Let’s take a stab at it.
Installing
First thing is to install it. I typically use piston to manage them. We need the at least version 1.9.x for its git support.
myapp $ cd vendor/plugins myapp/vendor/gems $ piston import git://github.com/technoweenie/acts_as_paranoid.git INFO main: Guessing the repository type INFO main: Guessing the working copy type INFO main: Checking out the repository INFO main: Copying from Piston::Revision(git://github.com/technoweenie/acts_as_paranoid.git@1e9144e483524b4f246a1768462eadb22f634f19) INFO main: Checked out "git://github.com/technoweenie/acts_as_paranoid.git" 1e9144e to "acts_as_paranoid"
Configuring
We now can define a model class to be paranoid:
Internally, acts_as_paranoid uses the deleted_at
column to track if something is deleted or not. So, we need to make a migration for it:
myapp $ script/generate migration MakeEventParanoid exists db/migrate create db/migrate/012_make_event_paranoid.rb
It should look something like:
You can now migrate:
myapp $ rake db:migrate == 12 AddDeletedAt: migrating ================================================= -- add_column("events", :deleted_at, :datetime) -> 0.3596s == 12 AddDeletedAt: migrated (0.3596s) ========================================
Using
It might be easiest to demonstrate with this snippet from script/console
:
>> event = Event.find(:first) => #<Event id: 91133883, date: "2008-04-28 00:00:00", description: "The Ezra event tonight has been cancelled.The Ezra ...", created_at: "2008-04-16 13:30:20", updated_at: "2008-05-30 23:43:22", location: "", lng: nil, lat: nil, title: "Meeting", deleted_at: nil> >> event.destroy! => #<Event id: 91133883, date: "2008-04-28 00:00:00", description: "The Ezra event tonight has been cancelled.The Ezra ...", created_at: "2008-04-16 13:30:20", updated_at: "2008-05-30 23:43:22", location: "", lng: nil, lat: nil, title: "Meeting", deleted_at: nil> >> Event.find(:first) => #<Event id: 420662881, date: "2008-04-15 00:00:00", description: "Worked on creating the app for this site, [bostonrb...", created_at: "2008-04-16 13:30:20", updated_at: "2008-05-29 01:19:41", location: nil, lng: nil, lat: nil, title: "Hackfest", deleted_at: nil> >> Event.find_with_deleted(:first) => #<Event id: 420662881, date: "2008-04-15 00:00:00", description: "Worked on creating the app for this site, [bostonrb...", created_at: "2008-04-16 13:30:20", updated_at: "2008-05-29 01:19:41", location: nil, lng: nil, lat: nil, title: "Hackfest", deleted_at: nil> >> event.deleted_at = nil => nil >> event.save! => true >> Event.find(:first) => #<Event id: 420662881, date: "2008-04-15 00:00:00", description: "Worked on creating the app for this site, [bostonrb...", created_at: "2008-04-16 13:30:20", updated_at: "2008-05-29 01:19:41", location: nil, lng: nil, lat: nil, title: "Hackfest", deleted_at: nil>
A synopsis:
- Find the first event
- Delete it
- Find the first event again, and see that it’s something else
- Find with deleted records, to see our original event
- Unset deleted_at to ‘undelete’ the orignal event.
Update: Fixed the script/console
section. Was using the wrong variable that I used earlier in the IRB session, but wasn’t displayed.