views:

540

answers:

4

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?

A: 

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?

andyjeffries
A: 

responsibility chain pattern

class Action { Perform(context); Undo(context); }

A: 

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.

Robin Bennett
+2  A: 

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.
Tilendor
Seems like Acts As Paranoid might have some problems with future versions of ActiveRecord since it overrides the find method.Acts As Soft Deletable looks good. I'm just wondering if the deleted_table gets out of sync how do I resync it?Have you used any of them before?
JasonOng
No, but in the description of soft deletable it says that it has helper methods built in to keep them in sync
Tilendor
A brief review of the two makes it seem like Acts as soft deletable would be the better choice, both for the method used and the fact that it appears to be better maintained.
Sam Murray-Sutton