Rails3 で Ajax (link_to_remote + will_paginate 対応)
Rails3 で Ajax 対応をする場合は下記のような感じで view を書いて、リクエストを受け取る側の Controller 等でも JavaScript を書かないと動かないようです。
<%= link_to('参照', {:action => 'show'}, :remote => true) %>
可能であればこれを勉強して Rails3 っぽく書きたいところなのですが、とりあえず Rails 2.x の link_to_remote に逃げる方法です。
(Rails3 の Ajax + RJS は後で勉強するつもりです(^^;)
まずは、prototype_legacy_helper を vendor/plugins に配置します。
$ cd vendor/plugins $ git clone git://github.com/rails/prototype_legacy_helper.git
これで view 上で link_to_remote が動作するようになるので、下記のような感じで記述できます。
<%= link_to_remote( '参照', { :url => {:action => 'show'}, :update => 'update_target', :loading => "showLoading('big', 'update_target')", } ) -%> <div id="update_target">ここを書き換えたい</div>
サーバからのレスポンスを待っている間は Alax っぽくロード中の画像を出したいので、:loading で showLoading を呼び出しています。
これは、下記の JavaScript を public/javascripts/application.js 等に書いておきます。
/* * ロード画面を出力する */ function showLoading(load_image_size, load_target) { // 画像オブジェクトの作成 img_element = document.createElement('img'); img_element.src = load_image_size == 'big' ? '/images/ajax-loader.gif' : '/images/ajax-loader-small.gif'; img_element.align = 'center'; // センタリングオブジェクト center_element = document.createElement('center'); center_element.appendChild(img_element); // 画像を表示するメソッド var output_loading = function(load_image, target_place) { target = document.getElementById(target_place); while (target.hasChildNodes()) { target.removeChild(target.firstChild); } target.appendChild(load_image); } // ロード画像を表示する場所が複数か否かの分岐 if (load_target instanceof Array) { for (var i = 0; load_target[i]; i ++) { output_loading(center_element, load_target[i]); } } else { output_loading(center_element, load_target); } }
/images/ajax-loader.gif や /images/ajax-loader-small.gif などの画像は Ajaxload - Ajax loading gif generator で自分好みの画像を作成すると良い感じになります。
これで link_to_remote での Ajax リクエストが実行できるようになります。
FORM から Ajax リクエストを実行したい場合は form_remote_tag を使用すれば、同様の動作を行うことが可能です。
ただし、prototype_legacy_helper は will_paginate に対応していないので別途対応が必要になります。
まず、app/helpers/remote_link_renderer.rb に下記のような内容を記述します。
(こちらは、id:donghai821 さんの記事を参考にさせていただきました)
class RemoteLinkRenderer < WillPaginate::LinkRenderer private def link(text, target, attributes = {}) if target.is_a? Fixnum page = target target = url(target) target[:url][:page] = page end @template.link_to_remote(text, target, attributes) end def url(page) @base_url_params ||= begin url_params = base_url_params merge_optional_params(url_params) url_params end url_params = @base_url_params.dup add_current_page_param(url_params, page) return url_params end end
次に will_paginate を下記のように記述すると、ページ送りも Ajax で動作するようになります。
<%= will_paginate( @users, :renderer => RemoteLinkRenderer, :params => { :url => {:action => 'show'}, :update => 'update_target', :loading => "showLoading('big', 'update_target')", }, :previous_label => '<- 前', :next_label => '次 ->' ) -%>