Capturing a form cancel
Feb 06, 2009
I've been meaning to write this one up for months now, ever since I originally posted the sexy forms in rails. The form builder I talk about in that post makes it easy to put a submit and cancel button on a the form, and a few people have asked how to handle the cancel action. Some have suggested using javascript to redirect back using an onclick, ick! What happens if the user doesn't have javascript support? Sure you might try and justify it by saying, "Well, how many users don't have javascript these days?" but there is absolutely no reason why this has to use javascript, so lets make it work for everybody.
It's actually much easier than you'd think, within application.rb I've got the following:
class ApplicationController < ActionController::Base
before_filter :catch_cancel, :update => [:create, :update, :destroy]
after_filter :set_referrer, :only => [:index, :show]
private
def set_referrer
session[:referrer] = url_for(params)
end
def catch_cancel
redirect_to session[:referrer] if params[:commit] == "Cancel"
end
end
The logic being, that if we've got a fully RESTful architecture the only pages we'll ever want to go "back" will be the index or show actions on each controller. So we cheekily call url_for in an after filter with the current params to get the path of the page we've just display the user, and stash it in the session. Theoretically it may be possible to use ENV["HTTP_REFERER"] instead but it's not guaranteed, this approach however ensures we keep track of the page to go back to explicitly ourselves.
Then, to piece it all together there's a before filter checking if the user has clicked the submit button labeled with "Cancel". You'll need to change that equality test dependent on what text you put on your button. You may also need to move the before filter into the controllers that require them, depending on the order it needs to run with other filters you have.
Hope that helps.
Previously I led the Terraform product team @ HashiCorp, where we launched Terraform Cloud and set the stage for a successful IPO. Prior to that I was part of the Startup Team @ AWS, and earlier still an early employee @ Heroku. I've also invested in a couple of dozen early stage startups.