おおいしつかさ


旅行とバイクとドライブと料理と宇宙が好き。
Ubie Discoveryのプログラマ。
Share:  このエントリーをはてなブックマークに追加

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

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も標準で含まれていました。もっと早く取り入れてほしかったですが、楽しみにしてまっていましょう。