RJSとform_remote_tagと。

RJSの中でform_remote_tagを使おうとして挫折しましたというお話。
page.replace_htmlで書き換えるHTMLにformを含みたかったのが事の発端。
いつもRHTMLの中で使うように

<% form_remote_tag :url => '/posts' do -%>
<div><%= submit_tag 'Save' %></div>
<% end -%>

をそのまま

form_remote_tag :url => '/posts' do
"<div>#{ submit_tag 'Save' }</div>"
end

のようにしてやったのだけれどダメ。ブロックの中身が出てこない。
しかもdevelopmentだというのにログにもさっぱり。
黙ってないでなにか言ったらどうなのだとばかりにRailsのソースへ・・・。



で、
actionpack-1.13.6/lib/action_view/helpers/prototype_helper.rb

172       def form_remote_tag(options = {}, &block)
173         options[:form] = true
...
180         form_tag(options[:html].delete(:action) || url_for(options[:url]), options[:html], &block)
181       end

ブロックはそのままform_tag()に渡っている。
actionpack-1.13.6/lib/action_view/helpers/form_tag_helper.rb

 33       def form_tag(url_for_options = {}, options = {}, *parameters_for_url, &block)
34         html_options = options.stringify_keys
...
50         if block_given?
51           content = capture(&block)
52           concat(tag(:form, html_options, true) + method_tag, block.binding)
53           concat(content, block.binding)
54           concat("</form>", block.binding)
55         else
56           tag(:form, html_options, true) + method_tag
57         end
58       end

このへん怪しいってことで50~55行目の間、地味にputsをはさんで流れを調べた結果、途中で例外が投げられてるみたい。

 56           tag(:form, html_options, true) + method_tag
57         end
58       rescue
59 p $!
60       end

すかさずこう(form_tag()全体にrescue)して捕まえてみたら

#<NameError: undefined local variable or method `_erbout' for #<#<Class:0xb7046944>:0xb704691c>>

なんぞこれ。
これが出ているのは
actionpack-1.13.6/lib/action_view/helpers/text_helper.rb

 25       def concat(string, binding)
26         eval("_erbout", binding).concat(string)
27       end

しかし、_erboutのスコープがどうなっているのかがさっぱりわからない。
RJSとRHTMLの違いを探しにrespond_toのところ(mime_responds.rb)を読みに行ったがもっとカオスだった。
たぶんblock.bindingだとかがちゃんと読めれば分かるのだろうけど。(希望的観測)

・・・

くっ!ブロックの理解が足りない!

タイトルとURLをコピーしました