public
Fork of davidhq/is_paranoid
Description: Destroy your records while keeping them in database, able to restore them later
Homepage:
Clone URL: git://github.com/mislav/is_paranoid.git
name age message
file MIT-LICENSE Sat Mar 21 08:17:45 -0700 2009 first commit [semanticart]
file README.markdown Wed Oct 14 19:24:48 -0700 2009 nicer, shorter README in markdown [mislav]
file Rakefile Wed Oct 14 13:55:27 -0700 2009 cleanup unnecessary cruft in specs [mislav]
file init.rb Sat Mar 28 07:27:04 -0700 2009 added init.rb (cherry picked from commit e9d59c... [davidhq]
file is_paranoid.gemspec Wed Oct 14 13:55:27 -0700 2009 cleanup unnecessary cruft in specs [mislav]
directory lib/ Fri Nov 27 07:42:16 -0800 2009 require "activerecord" is deprecated [mislav]
directory spec/ Wed Oct 14 14:02:01 -0700 2009 implement Model.find_only_destroyed() [davidhq]
README.markdown

Are you paranoid?

Destroying records is a one-way ticket--you are permanently sending data down the drain. Unless, of course, you are using this plugin.

Simply declare models paranoid:

class User < ActiveRecord::Base
  is_paranoid
end

You will need to add the "deleted_at" datetime column on each model table you declare paranoid. This is how the plugin tracks destroyed state.

Destroying

Calling destroy should work as you expect, only it doesn't actually delete the record:

User.count  #=> 1

User.first.destroy

User.count  #=> 0

# user is still there, only hidden:
User.count_with_destroyed  #=> 1

What destroy does is that it sets the "deleted_at" column to the current time. Records that have a value for "deleted_at" are considered deleted and are filtered out from all requests using default_scope ActiveRecord feature:

default_scope :conditions => {:deleted_at => nil}

Restoring

No sense in keeping the data if we can't restore it, right?

user = User.find_with_destroyed(:first)

user.restore

User.count  #=> 1

Restoring resets the "deleted_at" value back to nil.

Extra methods

Extra class methods provided by this plugin are:

  1. Model.count_with_destroyed(*args)
  2. Model.find_with_destroyed(*args)
  3. Model.find_only_destroyed(*args)

Pitfalls

  • validates_uniqueness_of does not ignore items marked with a "deleted_at" flag
  • various eager-loading and associations-related issues (see "Killing is_paranoid")
  • find/count_with_destroyed uses with_exclusive_scope and thus doesn't play nicely with named scopes