PUT|DELETEメソッドの謎

いままで全く気にしてもいなかったんだけど、Railsのlink_toて<a>タグ作ってるはずなのに、methodが指定できるのがふと不思議になってきました。どうなってんのでしょう?

まずはソース

生成されたソース見てみると

<a href="/icode/3" data-confirm="really delete?" data-method="delete" rel="nofollow">delete</a>

みたいな感じ。

「rel="nofollow"」は、「このページのリンクをたどらない」や「このリンクをたどらない」といった指示を検索エンジンに与える手段の 1 つ,

だ、そうなので、なんぞ data-methodのとこか。data-*ってのはHTML5のカスタム属性で、JSから*.datasetで簡単に取れます。
http://tokkono.cute.coocan.jp/blog/slow/index.php/xhtmlcss/html5-data-attributes-vs-jquery-data-api/
ここに詳しく載ってました。感謝。多謝。雨霰。
ともかく犯人はjsだよなとWeb inspector起動。

ここです。

    $(document).delegate(rails.linkClickSelector, 'click.rails', function(e) {
      var link = $(this), method = link.data('method'), data = link.data('params');
          :
      if (link.data('remote') !== undefined) {
          :
      } else if (link.data('method')) {
        rails.handleMethod(link);
        return false;
      }
    });

これだね。

    handleMethod: function(link) {
      var href = rails.href(link),
        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();
    },

うわーすごい。hidden formを生成して submitしてるのね。しかしformのmethodは"post"。hiddenで _methodを投げてるというへんてこ状態。なぜ?

なぜにpost??

というのは単純にブラウザ*1が PUT, DELETEなどに対応していない(サーバー側でも LIMITしている可能性がある)から、という認識であってるのかな。ともかくこういう動作をしているらしい。なんとなくRESTできれいなイメージで動いているものとばかり思っていたので騙されたような気持ち悪い感覚。やだなあ。
という訳で、RailsではRESTfulっぽくみせる疑似RESTになっている、というところまで理解した。
なるほど。

結論

とっととRESTに全移行しちゃって!!!*2

*1:正確にはHTMLの仕様.HTML5でも同様

*2:ブラウザというかHTMLの問題だけなので移行してない訳じゃないけども。しかしなぜHTML側でRESTな方向に行ってないんだろう? この辺り弱いっす・・・