Are you SURE?! (How to confirm HTTP methods in Rails) 14

Posted by sbecker Tue, 26 Jun 2007 15:15:00 GMT

Are you sure?

In Scott Raymond’s excellent book Ajax on Rails I came across a cool (non-ajax related) pattern for insuring a request’s method is POST and showing a confirmation form if not.

This is really useful in situations such as confirmation links in emails, where a form can’t be displayed and javascript won’t work, yet we don’t want a destructive action occurring through a GET request.

Here’s an example:

def unsubscribe
  if request.post?
    @user = User.find(params[:id])
    @user.update_attributes :subscribed => false
    redirect_to home_url
  else
    render :inline => %Q(
      <% form_tag do %>
        <%= submit_tag 'Confirm' %>
      <% end %>
    )
  end
end

One other piece of code you’ll need to get this to work, assumming you’re using RESTful routes, in config/routes.rb

map.resources :users, :member => {:subscribe   => :any, 
                                  :unsubscribe => :any}

This states that we have a couple extra actions in our controller, and we’re not going to mandate a specific HTTP method to get there. This way we can handle it within the action if the HTTP method is wrong.

Now if your user comes to your page from a straight GET request, he’ll get prompted to confirm the big destructive action he’s about to commit.

Simple Confirmation Form

(In a real app we’d make this form look a bit nicer.)

Wouldn’t it be nice if we could re-use this pattern, without writing out the inline form code every time? Seems generic enough.

DRY it up!

We could abstract that out, and also support any HTTP method we want. Lets follow Rails / RESTful conventions , and require PUT for updating a model. Using some handy ruby block syntax, we could write something like, say:

def unsubscribe
  confirm_unless :put do
    @user = User.find(params[:id])
    @user.update_attribute :subscribed, false
    flash[:notice] = "User is now unsubscribed"
    redirect_to users_url
  end
end

Much better. But how?! Keep reading.

Get one for yourself!

To get the confirm_unless method for yourself, slap the following code into app/controllers/application.rb:

def confirm_unless(method)
  if request.method == method
    yield
  else
    render :inline => %Q(
      <% form_tag({}, :method => :#{method}) do %>
        <%= submit_tag "Confirm" %>
      <% end %>
    )
  end
end

We could take it one step further and make it a before_filter, but I’ll leave that for a possible future post.

Comments

Leave a response

  1. Avatar
    Pratik Wed, 27 Jun 2007 11:28:00 GMT

    Nice example. A tiny tip : you don’t really need &block argument for yield – you can define your method as def confirm_unless(method)

  2. Avatar
    Scott Wed, 27 Jun 2007 16:31:09 GMT

    Pratik – Thanks! I removed the unnecessary &block argument. I’d wanted to make it clear that it was expecting a block. Not necessary though.

  3. online casino Sat, 01 Dec 2007 16:14:34 GMT

    Online Casino Tests. Spielen Sie Online Casino Spiele – wir haben eine Casino Bonus Übersicht mit den besten Casino Aktionsangeboten im Markt.

  4. Avatar
    christmas nativity scene Mon, 03 Dec 2007 04:58:33 GMT

    This is great! One question: Is there any way around the authentication issue? I have a portal which requires a login/password. Am I out of luck?

  5. Avatar
    gosurls Mon, 03 Dec 2007 12:55:15 GMT

    Very useful information. Thanks !

  6. Avatar
    urlsbox Tue, 04 Dec 2007 14:23:48 GMT

    Very useful information. Thanks !

  7. Avatar
    biturls Tue, 04 Dec 2007 14:24:02 GMT

    Very useful information. Thanks !

  8. Avatar
    solarurls Tue, 04 Dec 2007 14:24:32 GMT

    Very useful information. Thanks !

  9. Avatar
    wazzuplinks Tue, 04 Dec 2007 14:24:40 GMT

    Very useful information. Thanks !

  10. Avatar
    slotmaskiner Sat, 09 Feb 2008 16:04:16 GMT

    nice article

  11. Avatar
    needfornews Mon, 24 Mar 2008 12:49:23 GMT

    urls to the latest world news.

  12. Avatar
    needfornews Thu, 27 Mar 2008 12:03:50 GMT

    Try NeedForNews.com, a new comprehensive news aggregator. With NeedForNews, you don ’t really have to go anywhere else; NeedForNews has it all. needfornews.com vidslib.com

  13. Avatar
    needfornews Thu, 27 Mar 2008 12:03:57 GMT

    Try NeedForNews.com, a new comprehensive news aggregator. With NeedForNews, you don ’t really have to go anywhere else; NeedForNews has it all. needfornews.com vidslib.com

  14. Avatar
    feedogator Thu, 10 Apr 2008 10:38:51 GMT

    We search Feeds For You http://feedogator.com/

Comments