public
Description: A plugin for ActiveRecord that allows for easy recovery of deleted models.
Homepage:
Clone URL: git://github.com/aub/acts_as_recoverable.git
name age message
file .gitignore Thu Oct 16 13:37:27 -0700 2008 Initial checkin [Aubrey Holland]
file MIT-LICENSE Thu Oct 16 13:37:27 -0700 2008 Initial checkin [Aubrey Holland]
file README.rdoc Fri Oct 17 08:47:14 -0700 2008 More docs. [Aubrey Holland]
file Rakefile Thu Oct 16 13:37:27 -0700 2008 Initial checkin [Aubrey Holland]
directory generators/ Fri Oct 17 08:25:29 -0700 2008 Generator take 2 [Aubrey Holland]
file init.rb Thu Oct 16 13:37:27 -0700 2008 Initial checkin [Aubrey Holland]
file install.rb Thu Oct 16 13:37:27 -0700 2008 Initial checkin [Aubrey Holland]
directory lib/ Wed Dec 23 07:10:25 -0800 2009 Support attributes that are not stored in colum... [oggy]
directory tasks/ Thu Oct 16 13:37:27 -0700 2008 Initial checkin [Aubrey Holland]
directory test/ Wed Dec 23 07:10:25 -0800 2009 Support attributes that are not stored in colum... [oggy]
file uninstall.rb Thu Oct 16 13:37:27 -0700 2008 Initial checkin [Aubrey Holland]
README.rdoc

acts_as_recoverable

Paranoia got you down?

Acts as recoverable is a plugin for active record that provides a great way to restore objects that have been deleted. It’s similar in function to acts_as_paranoid, but puts a much smaller strain on the the developer (i.e. you) - especially with associations - and works correctly in a number of cases where acts_as_paranoid either doesn’t work or requires a whole lot of hacking. The plugin is designed to work in cases where you want to rescue the user from accidental deletion or allow them to recover deleted data in the future. And in order to make it work, you need exactly one line of code. The plugin works by serializing the deleted objects’ attributes, including associated objects, into a table. Objects stored in that table can be queried and recovered through a call that returns a copy of the original deleted object.

PROBLEMS, QUESTIONS, TODOS:

1) No API for recovering objects.

Setup

Install the plugin:

  ./script/plugin install git@github.com:aub/acts_as_recoverable.git

The plugin requires a table where it can store the data for deleted models. The table can be created easily enough:

  ./script/generate recoverable_objects_migration
  rake db:migrate

All set. The schema for the generated table is:

  create_table :recoverable_objects, :force => true do |t|
    t.text :object_hash
    t.timestamps
  end

Usage

Making a model recoverable

  class Article < ActiveRecord::Base
    acts_as_recoverable
  end

That was easy.

Destroying models so that they will be restorable

  @article.destroy

Hey, that looks familiar. Calling destroy! on the object will do a normal destroy and skip the recoverable process.

Recovering destroyed models

This I need to work on. At present, you would have to search for things in the RecoverableObjects table, and there is no great way to do so. Once you have that object, though:

  # will return an unsaved copy of the original object
  recoverable_object.recover

  # will return a saved copy of the original object and remove it from the
  # recoverable_objects table.
  recoverable_object.recover!

Dealing with associations

Associations? No problem. When a recoverable object is destroyed, data in :dependent => :destroy and has_and_belongs_to_many associations will be saved and recovered along with it. This works recursively, and objects in the associations are not required to be marked as recoverable in order to be saved.

  class Article < ActiveRecord::Base
    acts_as_recoverable
    has_many :comments, :dependent => :destroy
  end

  class Comment < ActiveRecord::Base
    belongs_to :article
  end

  a = Article.create(:comments => { Comment.create, Comment.create })
  a.destroy

  # This line intentionally left blank

  a = recoverable_object.recover
  a.comments.size  # => 2

Note that the Comment model does not itself have to be recoverable in order for this to work. With has_and_belongs_to_many, the ids of the associated objects are stored even if the association does not have :dependent => :destroy. Example:

  class Listing < ActiveRecord::Base
    has_and_belongs_to_many :locations
  end

  class Location < ActiveRecord::Base
    has_and_belongs_to_many :listings
  end

  l = Listing.create(:locations => { Location.create, Location.create })
  l.destroy

  # Again intentionally left blank

  l = recoverable_object.recover
  l.locations.size  # => 2

Spiffy!

License

Copyright © 2008 Aubrey Holland, patch, released under the MIT license