link_to に :method => :delete を指定した時の動作

以下 Rails 3.2.2 について記述します。
scaffold 等で作られる削除のリンクは次のようになっていると思います。

<%= link_to 'Delete', users_path(@user), :method => :delete, :confirm => 'Are you sure?' %>

これと同じコードを手で書いて使おうとしたのですが、なぜか正しく動作せず、少しはまってしまいました。結論から言うと、このコードが生成するリンクタグを動作させるには最低限 jquery.js と rails.js を読み込む必要があります(もちろん、それらの動作に対応したブラウザを使う必要もあります)。

そういうわけで、上記のコードを用いる時はレイアウト等で

<%= javascript_include_tag "application" %>

と記述するのを忘れないように気をつけてください。

ここから細かい解説、上の link_to は次のようなタグに展開されます。

<a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>

これを解釈して動作させているのが rails.js です。ソースが公開されているので、確認してみます。

https://github.com/rails/jquery-ujs/blob/master/src/rails.js

記事執筆段階では160行目からが該当箇所になります。

    // Handles "data-method" on links such as:
    // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
    handleMethod: function(link) {
      var href = link.attr('href'),
        method = link.data('method'),
        target = link.attr('target'),
        csrf_token = $('meta[name=csrf-token]').attr('content'),
        csrf_param = $('meta[name=csrf-param]').attr('content'),
        form = $('<form method="post" action="' + href + '"></form>'),
        metadata_input = '<input name="_method" value="' + method + '" type="hidden" />';

      if (csrf_param !== undefined && csrf_token !== undefined) {
        metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
      }

      if (target) { form.attr('target', target); }

      form.hide().append(metadata_input).appendTo('body');
      form.submit();
    },

このように、本来 DELETE メソッドでアクセスした際に行われる削除のアクションを form タグから _method を指定して再現しています。CSRF 対策の hidden タグ埋め込みも行っているので csrf_meta_tags も記述しないと動作しないかと思ったのですが、開発環境で動かしている限り問題ないようでした。