submit_tagの :disable_withオプション

Rails2.1.0で動いていたフォームの挙動が、Rails2.2.2でおかしくなったので調べてみたら、Actionpackの問題(バグ?)だったというオチ。

現象

まず、『<%= submit_tag '新規登録', :disable_with => '登録中です...' %>』というコードがIE8(7,6も同じだと思う)でエラーになります。
『hiddenCommit.setAttribute('type', 'hidden');』の'type'属性がリードオンリーなのにセットしようとしているところがマズイらしいので、ここだけコメントアウトしてやってみると、今度は『新規登録』ボタンをクリックすると下側に新しく『新規登録』ボタンがボコっと出てきます。
Actionpackの form_tag_helper.rbを見てみると、『this.form.appendChild(hiddenCommit)』でボタンを作っていて、ここの属性が 'hidden'にできないから新しいボタンが見えてしまうと。

対処

 # options["onclick"]  = "if (window.hiddenCommit) { window.hiddenCommit.setAttribute('value', this.value); }"
 # options["onclick"] << "else { hiddenCommit = this.cloneNode(false);hiddenCommit.setAttribute('type', 'hidden');this.form.appendChild(hiddenCommit); }"
   options["onclick"]  = "this.setAttribute('originalValue', this.value);this.disabled = true;#{disable_with};"
   options["onclick"] << "result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit());"
   options["onclick"] << "if (result == false) { this.value = this.getAttribute('originalValue');this.disabled = false; }return result;"

actionpack-2.x.x\lib\action_view\helpers\form_tag_helper.rb』の該当箇所2行(actionpack-2.1.2から追加されたらしい)が邪魔なので、ここをコメントアウトしてしまいます。

追記:actionpackを直にいじるのはお行儀が悪いので、application_helper.rbに submit_tagを再定義(オーバーライド)しておきます。

module ActionView
  module Helpers
    module FormTagHelper
      def submit_tag(value = "Save changes", options = {})
                       :
                       :
 if (window.hiddenCommit) {
   window.hiddenCommit.setAttribute('value', this.value);
 }
 else {
   hiddenCommit = this.cloneNode(false);
   hiddenCommit.setAttribute('type', 'hidden');
   this.form.appendChild(hiddenCommit);
 }

この部分、どういう理由で付け加えられたんでしょうかね。submitの結果を待たずに画面遷移された場合などにボタンの表示が戻らないケースがあるから hiddenCommitにとっておいてそれを戻すということなんでしょうか。
そうだとすると、『hiddenCommit.setAttribute('type', 'hidden');』をエラーが出ないように書き換えるべきなんでしょうけど、これがなくて特に不自由な感じがしないので、しばらくはこのモンキーパッチでいくことにします。