初めまして.morimorihogeといいます.Webアプリの開発をすることが多いので,主にそっち系の記事を書いていくことになるかと思いますので,よろしくお願いします.
さて,Rails 3でwill_paginateを使っているときに,remote => true
的なことをやりたくてググっていたのですが,世の中で見つかる事例がwill_paginate 2系の記事ばかりだったので,自己解決した結果を書いておきます.ちなみにRails 3.0.3 + will_paginate 3.0.pre2で動作確認しています.
具体的にはどういう事かというと,will_paginate
を使うと,
<%= will_paginate @posts %>
としたものはaタグのリンクリストになるのですが,これは通常のaタグであるため,ページ遷移が発生します.
具体的には,コンテンツをAjaxを使って作っていて,
- views/home/index.html.erb
<script type="text/javascript">// <![CDATA[
$(function(){
$.ajax({
type: 'GET',
url: '<%= posts_url %>',
dataType: 'script'
});
});
// ]]></script>
- controllers/posts_controller.rb
def index
@sort_field = params[:sort] || “updated_at”
@sort_order = params[:order] || :desc
@posts = Post.paginate(
:page => params[:page], :per_page => params[:per_page] || 20,
:order => “#{@sort_field} #{@sort_order}”
)
respond_to do |format|
format.js
end
end
- views/posts/index.rjs
page.replace_html ‘posts_table’, :partial => ‘posts/list’,
:locals => {:posts => @posts}
- views/posts/_list.html.erb
<%= will_paginate @posts %>
<%= will_paginate @posts %>
みたいなコードを書いていた時にwill_paginate
に出力してもらいたいリンクは,以下の様なdata-remote
, data-remote
属性が設定されたaタグであってほしいわけです..
<a href="/posts?page=1" data-remote="true" data-method="get">1</a>
通常のlink_to
ヘルパを使えば以下の様になります.Rails3からはlink_to_remote
ではなくて:remote => true
を使うようになっていますね.
<%= link_to posts_path(:page => 1), :remote => true %>
この辺りの解決策をぐぐると,この辺りやこの辺りが出てきたのですが,いくらやってもうまく行かず,結局will_paginateのソースを追いかけてみたところ,そもそも3.0.pre2ではpage_link
メソッド自体が廃止されていました.
というわけで,will_paginate 3.0.pre2では,以下のようにすればOKです.
- lib/remote_pagination_list_link_renderer.rb
class RemotePaginationListLinkRenderer < WillPaginate::ViewHelpers::LinkRenderer
private
# :remote => true
def link(text, target, attributes = {})
if target.is_a? Fixnum
attributes[:rel] = rel_value(target)
target = url(target)
end
attributes[:href] = target
attributes[“data-remote”] = true
attributes[“data-method”] = :get
tag(:a, text, attributes)
end
end
- views/posts/_list.html.erb
<%= will_paginate @posts,
:renderer => RemotePaginationListLinkRenderer %>
(Post一覧は省略)
<%= will_paginate @posts,
:renderer => RemotePaginationListLinkRenderer %>
これで,:renderer => RemotePaginationListLinkRenderer
を付けて呼び出したwill_paginate
はAjax呼び出しになります.
ちなみに,毎回Rendererを指定するのが面倒であれば,以下の設定をする手もあります.ただ,この場合全てのwill_paginate
がAjax呼び出しになるので注意です.
- config/initializers/will_paginate.rb
# for :remote option
WillPaginate::ViewHelpers.pagination_options[:renderer] = 'RemotePaginationListLinkRenderer'
ではでは〜