Question

I think it important to have an "undo" method ala gmail when destroying records instead of displaying an annoying popup that says, "Are you sure?".

The way that I've implemented this is to have a "deleted_at" timestamp column in the model which gets timestamped when destroy method is called

def destroy
  @foo = Foo.find(params[:id])
  @foo.update_attribute(:deleted_at, Time.now)
  ...
end

To revert/undo I'll just set the same column to nil

def revert
  @foo = Foo.find(params[:id])
  @foo.update_attribute(:deleted_at, nil)
  ...
end

I'll just have to add a condition to filter off "deleted" foos when I call the find method. Perhaps set a cron or background task to really destroy "deleted" foos after some time.

Works for me and easy to implement but I'm curious as to if there's a better way to implement this feature? Maybe there's a plugin or gem that provides this that I don't know about?

Was it helpful?

Solution

There are indeed some plugins that can be found at Agile Web Development.

Here are the links and summaries for the plugins which seem to match your description:

  1. Acts as Paranoid: Make your Active Records "paranoid." Deleting them does not delete the row, but set a deleted_at field. Find is overloaded to skip deleted records.
  2. Acts as soft deletable: Provides the ability to soft delete ActiveRecord models.

OTHER TIPS

There is a file here that seems to do what you're requiring, but personally I think there must be something out there that automatically filters out deleted records unless you specifically include them. That way they really would appear deleted unless you include a parameter or a named scope that re-includes them.

Unfortunately, I haven't written one and spare time is limited, but it shouldn't be that hard, should it?

You can move the deleted items into a separate collection (or table, or whatever) - then anything that looks in the original list will see that it's been deleted, and you can deal with the new list when it's convenient.

PaperTrail does this nicely. There is a good Railscast on it, although it is a little old now. I know this question was asked quite a while ago but I stumbled upon it out of curiosity and thought I should reference a nice up to date way of doing this.

responsibility chain pattern

class Action
{
  Perform(context);
  Undo(context);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top