Rails3のAjaxでHTMLを返してjQueryで処理する
6月末くらいからRailsを触り始め、ようやく慣れてきたと思ったらRails3が出て涙を流してるのがおれです。そんなわけで会社のプロジェクトをRails3で書きなおしてます。
Rails2時代
Rails2時代のAjaxのリクエストは、link_to_remoteを使えば問題ありませんでした。こんな感じ
<%= link_to_remote "hoge", :url => hoge_path,:update => "hoge_id" %>
こうするとhoge_pathっていうURLにAjaxで通信して、返ってきたレスポンスでid="hoge_id"な要素以下を更新してくれてました。
Rails3時代
Rails3ではlink_to_remoteは廃止され、代わりに:remote => trueを使うようになりました。あと:updateもなくなったみたいです。こんな感じです。
<%= link_to "hoge", hoge_path, :remote => true %>
これでコントローラにアクセスをして、hoge.js.erbみたいな.js.erbなファイルをrenderするようにします。hoge.js.erbはこんな感じ
$("#hoge_id").html("abababa"); //こういうふうに書いてもいい $("#hoge_id").html("<%= escape_javascript(render @hoge) %>");
Rails3からできたrails.jsがサーバから返ってきたJSをコールしてくれてるようです。まぁこれでもいいんですけど、hoge.js.erbを作った上に、renderするHTMLも作るとか手間だし、Ajaxで返ってきたレスポンスで指定したID以下を書き換えるとかはもっと簡単にやりたい。ようするにRails2の時にやってたみたいにしたいなぁと思って色々調べました。
解決策
:remote => trueでリクエストを送ると、.js.erbが返ってきてしまい、.html.erbを返したくてもMissingTemplateというエラーが出てしまいます。HTMLをレスポンスとして受け取りたい場合には、link_toでdata-typeという属性でhtmlを指定すればできます。こんな感じ
<%= link_to "hoge", hoge_path, :remote => true, "data-type" => "html","id" => "hoge_link" %>
これでサーバ側でhoge.html.erbをrenderすれば良いです。他の形式で返したい場合は、jQueryのdataTypeに合うものであればなんでも行けると思います。
次に返ってきたレスポンスをjavascriptで処理する方法です。Ajaxの成功イベントは、(rails.jsでは?)ajax:successというイベントで取得できます。こんな感じ
$(function(){ $("#hoge_link").live("ajax:success",function(data,status,xhr){}); });
この二つが分かれば、Rails2の時にやってた:updateの指定みたいなのができそうです。というわけで僕は次のようにしました。
<script type="text/javascript"> $(function(){ $("a[data-update]") .live("ajax:success",function(data,status,xhr){ var link = $(this); $("#" + link.attr("data-update")).html(status); }); }); </script> <%= link_to "hoge",hoge_path, :remote => true, "data-type" => "html", "data-update" => "hoge_id" %>
linkにdata-updateという属性を持たせて、それの値に更新したいIDを指定します。jQueryの方ではdata-updateという属性を持つものに対して、Ajaxで返ってきたレスポンスでdata-updateで指定したIDのhtmlを書き換えるという処理をさせてます。
このノリで行けば、:loadingや:beforeも行けそうな気がします。
これで良いのかわからないですが、ひとまず動いたので個人的には良しとします。他にいい方法があったら教えてください。