Ruby on Rails
Undo Helper Plugin (Version #3)

Maintains a stack of undo actions in the session, so users can cancel actions by clicking the Undo button.

Use undo.push to add a new undo action, and undo.pop to remove it. Use undo.render to render the Undo button.

Here’s the Rails controller with a create action that creates a new record, a delete action that will undo it, and a before_filter that removes undo actions from the stack:


# Remove undo action from stack.
before_filter do |controller|
    controller.undo.pop(controller.params) if controller.params[:undo]
end

# The create action creates a new record, the undo action deletes it.
def create()
    # Do something useful here
    record = Record.create(@params)
    # If this is not an undo, add an undo action to delete the record.
    unless @params[:undo]
        undo.push ("Delete newly created record",
            :action=>"delete", :id=>record.id)
    end
    # Render page (see below).
    . . .
end

def delete()
    . . .
end

A third method renders the undo form and button, using the last undo action from the stack. The view creates a wrapper element and renders an action:


<div id="undo"><%= undo.render %></div>

For AJAX requests, I use RJS to instruct the browser to update the undo button without reloading:


render :update do |page|
    page["undo"].replace_html undo.render
end

Maintains a stack of undo actions in the session, so users can cancel actions by clicking the Undo button.

Use undo.push to add a new undo action, and undo.pop to remove it. Use undo.render to render the Undo button.

Here’s the Rails controller with a create action that creates a new record, a delete action that will undo it, and a before_filter that removes undo actions from the stack:


# Remove undo action from stack.
before_filter do |controller|
    controller.undo.pop(controller.params) if controller.params[:undo]
end

# The create action creates a new record, the undo action deletes it.
def create()
    # Do something useful here
    record = Record.create(@params)
    # If this is not an undo, add an undo action to delete the record.
    unless @params[:undo]
        undo.push ("Delete newly created record",
            :action=>"delete", :id=>record.id)
    end
    # Render page (see below).
    . . .
end

def delete()
    . . .
end

A third method renders the undo form and button, using the last undo action from the stack. The view creates a wrapper element and renders an action:


<div id="undo"><%= undo.render %></div>

For AJAX requests, I use RJS to instruct the browser to update the undo button without reloading:


render :update do |page|
    page["undo"].replace_html undo.render
end