Rails3.0.4で、link_to ヘルパーメソッドにconfirmやmethodを混ぜるときの注意

Tsukasa OISHI

Rails3.0.4以前のRails3系で、link_toヘルパメソッドにconfirmとmethodを混ぜていると、ブラウザによっては想定していない挙動をすることがあります。

<%= link_to "削除", {:action => :delete, :id => item_id}, 
                               :confirm => "本当に削除しますか?", :method => :delete %>

というようなコードを書いて確かめると、Firefox等では問題がないのにIEだとconfirmでキャンセルを選択してもdeleteアクションが実行されてしまいました。

このあたりの挙動は、rails.jsの中で実装されています。

  document.on("click", "*[data-confirm]", function(event, element) {
    var message = element.readAttribute('data-confirm');
    if (!confirm(message)) event.stop();
  });

  document.on("click", "a[data-remote]", function(event, element) {
    if (event.stopped) return;
    handleRemote(element);
    event.stop();
  });

  document.on("click", "a[data-method]", function(event, element) {
    if (event.stopped) return;
    handleMethod(element);
    event.stop();
  });

調べてみると、IEのときは先に data-methodの関数がコールされていました。どのイベントが先に呼ばれるかはブラウザによるようです。
Railsのedgeを調べてみるとrails.jsがなくなっていて、prototype_ujs.jsというところで実装されていました。

document.on('click', 'a[data-confirm], a[data-remote], a[data-method]', function(event, link) {
    if (!allowAction(link)) {
      event.stop();
      return false;
    }

    if (link.readAttribute('data-remote')) {
      handleRemote(link);
      event.stop();
    } else if (link.readAttribute('data-method')) {
      handleMethod(link);
      event.stop();
    }
  });

allowActionという関数は、confirmがあればそれをコールして結果を返します(なければtrueが返ります)。ひとつの関数で、三つの挙動を行うように修正されています。
なので、Rails3.0.4でもこのあたりのコードをもってくるとよさそうです。

ちなみにegdeのRailsではjQueryも標準で含まれていました。もっと早く取り入れてほしかったですが、楽しみにしてまっていましょう。