<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Synthesis: Are you SURE?! (How to confirm HTTP methods in Rails)</title>
    <link>http://synthesis.sbecker.net/articles/2007/06/26/are-you-sure</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>by Scott Becker</description>
    <item>
      <title>Are you SURE?! (How to confirm HTTP methods in Rails)</title>
      <description>&lt;p&gt;&lt;a href="http://synthesis.sbecker.net/articles/2007/06/26/are-you-sure"&gt;&lt;img src="http://synthesis.sbecker.net/files/are_you_sure.png" title="Are you sure?" alt="Are you sure?" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;In &lt;a href="http://scottraymond.net/"&gt;Scott Raymond&amp;#8217;s&lt;/a&gt; excellent book &lt;a href="http://www.oreilly.com/catalog/9780596527440/"&gt;Ajax on Rails&lt;/a&gt; I came across a 
cool (non-ajax related) pattern for insuring a request&amp;#8217;s method is &lt;span class="caps"&gt;POST&lt;/span&gt; and
showing a confirmation form if not.&lt;/p&gt;


	&lt;p&gt;This is really useful in situations such as confirmation links in
emails, where a form can&amp;#8217;t be displayed and javascript won&amp;#8217;t work,
yet we don&amp;#8217;t want a destructive action occurring through a &lt;span class="caps"&gt;GET&lt;/span&gt; request.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s an example:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;unsubscribe&lt;/span&gt;
  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;post?&lt;/span&gt;
    &lt;span class="attribute"&gt;@user&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:id&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
    &lt;span class="attribute"&gt;@user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;update_attributes&lt;/span&gt; &lt;span class="symbol"&gt;:subscribed&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;
    &lt;span class="ident"&gt;redirect_to&lt;/span&gt; &lt;span class="ident"&gt;home_url&lt;/span&gt;
  &lt;span class="keyword"&gt;else&lt;/span&gt;
    &lt;span class="ident"&gt;render&lt;/span&gt; &lt;span class="symbol"&gt;:inline&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;%Q(&lt;/span&gt;&lt;span class="string"&gt;
      &amp;lt;% form_tag do %&amp;gt;
        &amp;lt;%= submit_tag 'Confirm' %&amp;gt;
      &amp;lt;% end %&amp;gt;
    &lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;One other piece of code you&amp;#8217;ll need to get this to work, assumming you&amp;#8217;re using
RESTful routes, in config/routes.rb&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;map&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;resources&lt;/span&gt; &lt;span class="symbol"&gt;:users&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:member&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;&lt;span class="symbol"&gt;:subscribe&lt;/span&gt;   &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:any&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; 
                                  &lt;span class="symbol"&gt;:unsubscribe&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:any&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;This states that we have a couple extra actions in our controller, and we&amp;#8217;re not
going to mandate a specific &lt;span class="caps"&gt;HTTP&lt;/span&gt; method to get there. This way we can handle it
within the action if the &lt;span class="caps"&gt;HTTP&lt;/span&gt; method is wrong.&lt;/p&gt;


	&lt;p&gt;Now if your user comes to your page from a straight &lt;span class="caps"&gt;GET&lt;/span&gt; request,
he&amp;#8217;ll get prompted to confirm the big destructive action he&amp;#8217;s about to commit.&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://synthesis.sbecker.net/files/confirm_form.PNG" title="Simple Confirmation Form" alt="Simple Confirmation Form" /&gt;&lt;/p&gt;


	&lt;p&gt;(In a real app we&amp;#8217;d make this form look a bit nicer.)&lt;/p&gt;


	&lt;p&gt;Wouldn&amp;#8217;t it be nice if we could re-use this pattern, without writing out the inline
form code every time? Seems generic enough.&lt;/p&gt;


	&lt;h1&gt;&lt;span class="caps"&gt;DRY&lt;/span&gt; it up!&lt;/h1&gt;


	&lt;p&gt;We could abstract that out, and also support any &lt;span class="caps"&gt;HTTP&lt;/span&gt; method we want.
Lets follow &lt;a href="http://www.softiesonrails.com/2007/4/18/rest-101-part-4-routing"&gt;Rails / RESTful conventions&lt;/a&gt; , and require &lt;span class="caps"&gt;PUT&lt;/span&gt; for updating a model.
Using some handy ruby block syntax, we could write something like, say:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;unsubscribe&lt;/span&gt;
  &lt;span class="ident"&gt;confirm_unless&lt;/span&gt; &lt;span class="symbol"&gt;:put&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="attribute"&gt;@user&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:id&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
    &lt;span class="attribute"&gt;@user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;update_attribute&lt;/span&gt; &lt;span class="symbol"&gt;:subscribed&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;
    &lt;span class="ident"&gt;flash&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:notice&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;User is now unsubscribed&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;redirect_to&lt;/span&gt; &lt;span class="ident"&gt;users_url&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Much better. But how?! Keep reading.&lt;/p&gt;


	&lt;h1&gt;Get one for yourself!&lt;/h1&gt;


	&lt;p&gt;To get the &lt;strong&gt;confirm_unless&lt;/strong&gt; method for yourself, slap the following
code into app/controllers/application.rb:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;confirm_unless&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;method&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;method&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="ident"&gt;method&lt;/span&gt;
    &lt;span class="keyword"&gt;yield&lt;/span&gt;
  &lt;span class="keyword"&gt;else&lt;/span&gt;
    &lt;span class="ident"&gt;render&lt;/span&gt; &lt;span class="symbol"&gt;:inline&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;%Q(&lt;/span&gt;&lt;span class="string"&gt;
      &amp;lt;% form_tag({}, :method =&amp;gt; :&lt;span class="expr"&gt;#{method}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="string"&gt;
        &amp;lt;%= submit_tag &amp;quot;Confirm&amp;quot; %&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt; &lt;span class="punct"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="string"&gt;
    )
  end
end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;We could take it one step further and make it a before_filter, but I&amp;#8217;ll leave that for a possible future post.&lt;/p&gt;</description>
      <pubDate>Tue, 26 Jun 2007 08:15:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:c839fe0b-e16d-44dc-ad57-e921e3d539df</guid>
      <author>sbecker</author>
      <link>http://synthesis.sbecker.net/articles/2007/06/26/are-you-sure</link>
      <category>Ruby on Rails</category>
      <category>Web Development</category>
      <category>confirm</category>
      <category>http</category>
      <category>REST</category>
    </item>
    <item>
      <title>"Are you SURE?! (How to confirm HTTP methods in Rails)" by feedogator</title>
      <description>&lt;p&gt;We search Feeds For You
&lt;a href="http://feedogator.com/" rel="nofollow"&gt;http://feedogator.com/&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 10 Apr 2008 03:38:51 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:9f596b3b-9aad-4f87-801b-590f4193e6ef</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/26/are-you-sure#comment-7834</link>
    </item>
    <item>
      <title>"Are you SURE?! (How to confirm HTTP methods in Rails)" by needfornews</title>
      <description>&lt;p&gt;urls to the latest world news.&lt;/p&gt;</description>
      <pubDate>Mon, 24 Mar 2008 05:49:23 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:897eb780-7859-4e3b-b7f2-c7c38b1fb40f</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/26/are-you-sure#comment-7822</link>
    </item>
    <item>
      <title>"Are you SURE?! (How to confirm HTTP methods in Rails)" by Scott</title>
      <description>&lt;p&gt;Pratik &amp;#8211; Thanks! I removed the unnecessary &amp;#38;block argument. I&amp;#8217;d wanted to make it clear that it was expecting a block. Not necessary though.&lt;/p&gt;</description>
      <pubDate>Wed, 27 Jun 2007 09:31:09 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:c68cae88-c657-456e-9706-74570014d11f</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/26/are-you-sure#comment-7458</link>
    </item>
    <item>
      <title>"Are you SURE?! (How to confirm HTTP methods in Rails)" by Pratik</title>
      <description>&lt;p&gt;Nice example. A tiny tip : you don&amp;#8217;t really need &amp;#38;block argument for yield &amp;#8211; you can define your method as def confirm_unless(method)&lt;/p&gt;</description>
      <pubDate>Wed, 27 Jun 2007 04:28:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:cf139b3a-8cc8-43cb-a64a-f40c8ea9b7f1</guid>
      <link>http://synthesis.sbecker.net/articles/2007/06/26/are-you-sure#comment-7456</link>
    </item>
  </channel>
</rss>
