初めまして.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'
ではでは〜
 
      