ANN: rails-undo-redo

Posted on Mon Feb 18 01:03:00 UTC 2008

To this day, very few web apps provide any undo/redo capabilities. This is really not such a good thing for usability. There are a few exceptions like gmail, but it does not go far enough to provide what every one is used on their desktop.

Ever since I read Assaf’s post on the subject, and left hungry for more, as Assaf only helps you on the UI side and leaves you all the heavy lifting, I have been thinking that there must be a way to make it a lot easier to implement undo/redo in a consistent manner, and in a way that is as easy as rails has gotten us used to.

After a few failed attempts, and building on the work of Brian Durand and his Acts As Revisionable and ActsAsTrashable plugins, that I’ve reused (and probably abused as well), I have come to realize a few (obvious?) things, namely that:

for Undo/Redo to work, it needs to

  • Work across all models
  • Capture the list of changed objects (UndoRecords)
  • Group these UndoRecords per User Action (UndoActions)

Then undo and redo are just a simple matter of replaying the UndoRecords in the right order.

All my previous attempts, and most other plugins I got inspiration from focused on one model, and even though you need this as a building block, for any real application, you need to be able to undo changes across multiple models (even beyond belongs_to, has_many type changes).

When you look at the types of changes to a model in details, you really have 3 types of changes Create, Update and Destroy (these are the C-U-D in CRUD, even if you are not doing REST), and undoing each one requires special handling, so this is also tracked and managed by UndoRecord.

To make a long story short, I’ve packaged all these ideas into a new Rails plugin: Rails Undo Redo (and very soon a gem as well, because this can help, and that’s also easy, or very easy), you can now easily transform any Rails Application using Active Record into a full fledged multi level undo/redo application like most desktop application.

For a full how-to, read the Rails Undo Redo project page, or try the Rails Undo Redo demo.

Posted in News, Rails  |  Tags  |  7 comments

Comments

  1. Antoine Antoine said // Feb 18, 2008 at 02:26 AM

    Hi Pascal,

    this sounds like a great addition. I am curious though: do you keep track of the revisions of a record ? Is it possible to visualize them ?

  2. Pascal Pascal said // Feb 18, 2008 at 02:38 AM

    The undo data is kept in a separate record independent from the original model. The same way Acts As Revisionable does it, and unlike something like Acts As Versioned.

    Assuming you know what the UndoManager is (UndoManager.current), then you can find the UndoActions (undo_manager.undo_actions), from there, the UndoRecords (undo_action.undo_records).

    The data is stored as a compressed blob, but the inspect method of UndoRecord will show what the object looks like.

    I’ll be documenting in more details how this works.

  3. Alicia Alicia said // Feb 18, 2008 at 05:27 AM

    This is perfect! The trouble with me working with rails is that i always tweak something accidentally. This should be of great help!

  4. Jake Jake said // Mar 15, 2008 at 11:52 AM

    It shows

    undefined local variable or method `undo_path’ for #<actionview::base:0x2540234>

    I guess you forgot to include some routing changes.

  5. Pascal Pascal said // Mar 21, 2008 at 12:28 AM

    Indeed! Here are the missing routes

    map.undo 'undo', :controller => "welcome", :action => "undo"

    map.redo 'redo', :controller => "welcome", :action => "redo"

    In fact, any controller should do since undo and redo are added to all controllers. “

  6. David Ward David Ward said // May 02, 2008 at 03:13 AM

    Magic, Alicia I’m with you, I’m constantly tinkering! Good work guys!

  7. Chris Whatley Chris Whatley said // May 12, 2008 at 07:51 AM

    This is great cheers guys

(leave url/email »)

Comment Markup Help