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.

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 ?
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.
This is perfect! The trouble with me working with rails is that i always tweak something accidentally. This should be of great help!
It shows
undefined local variable or method `undo_path’ for #<actionview::base:0x2540234>
I guess you forgot to include some routing changes.
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. “
Magic, Alicia I’m with you, I’m constantly tinkering! Good work guys!
This is great cheers guys