AutoPagerizeなwill_paginateにしておく
classic_paginationのREAD_MEには、以下のように書かれている。
This code was extracted from Rails trunk after the release 1.2.3. WARNING: this code is dead. It is unmaintained, untested and full of cruft.
There is a much better pagination plugin called will_paginate. Install it like this and glance through the README:
script/plugin install svn://errtheblog.com/svn/plugins/will_paginate
It doesn‘t have the same API, but is in fact much nicer. You can have both plugins installed until you change your controller/view code that handles pagination. Then, simply uninstall classic_pagination.
classic_paginationはRails1.2.3から取り出されたコードで、メンテナンスもテストもされていないと...。will_paginateという、より素晴らしいpaginationプラグインがあるらしい。どうもそちらがお勧めのようだ*1。警告を読むと、will_paginateをインストールせずにはいられない。早速インストールして使ってみた。
インストール
$ gem install will_paginate
- will_paginateを利用したいRailsプロジェクトで、config/environment.rbの最後に以下を追記することで、will_paginateが有効になる。
require 'will_paginate'
- 上記に書かれている通りのコマンドでインストール。
script/plugin install svn://errtheblog.com/svn/plugins/will_paginate
基本
- findメソッドと同じ感覚で利用できるようだ。
- :page => params[:page]オプションは必須。無いとエラーが発生し、:page parameter requiredのメッセージ。
# コントローラー: app/controllers/slips_controller.rb class SlipsController < ApplicationController ...(中略)... def list #@slip_pages, @slips = paginate(:slips, :per_page => 4) @slips = Slip.paginate(:page => params[:page], :per_page => 4) # 以下のような条件指定もOK。詳細はマニュアルを。 #@slips = Slip.paginate(:page => params[:page], :per_page => 4, :conditions=>["total_yen>?", 1000], :order=>"number DESC, id DESC") end ...(中略)...
- ページリンクの生成にはwill_paginateヘルパメソッドを使う。日本語で「前」「次」と表示するようにしてみた。
<%# ビュー: app/views/slips/list.rhtml %> <table> <% for slip in @slips %> <tr id="<%= partial_path(slip) %><%= dom_id(slip) %>"> <% for column in Slip.content_columns %> <td><%=h slip.send(column.name) %></td> <% end %> <td><%= link_to 'Show', :action => 'show', :id => slip %></td> <td><%= link_to 'Edit', :action => 'edit', :id => slip %></td> <td><%= link_to 'Destroy', { :action => 'destroy', :id => slip }, :confirm => 'Are you sure?', :method => :post %></td> </tr> <% end %> </table> ...(中略)... <%#= link_to 'Previous page', { :page => @slip_pages.current.previous }, {:rel=>'prev'} if @slip_pages.current.previous %> <%#= link_to 'Next page', { :page => @slip_pages.current.next }, {:rel=>'next'} if @slip_pages.current.next %> <%= will_paginate @slips, :prev_label=>'«前', :next_label=>'次»' %> ...(中略)...
/* スタイルシート: public/stylesheets/will_paginate.css */ .pagination { padding: 3px; margin: 3px; } .pagination a { padding: 2px 5px 2px 5px; margin: 2px; border: 1px solid #aaaadd; text-decoration: none; color: #000099; } .pagination a:hover, .pagination a:active { border: 1px solid #000099; color: #000; } .pagination span.current { padding: 2px 5px 2px 5px; margin: 2px; border: 1px solid #000099; font-weight: bold; background-color: #000099; color: #FFF; } .pagination span.disabled { padding: 2px 5px 2px 5px; margin: 2px; border: 1px solid #eee; color: #ddd; }
- レイアウトで上記スタイルシートを読み込む。
<%# レイアウト: app/views/layouts/slips.rhtml %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>Slips: <%= controller.action_name %></title> <%= stylesheet_link_tag 'scaffold', 'will_paginate' %><%#<--- 'will_paginate'を追記 %> <%= javascript_include_tag :defaults %> </head> <body> <p style="color: green"><%= flash[:notice] %></p> <%= yield %> </body> </html>
Ruby on Rails 2.0.1に対応 - idesaku blogがとても参考になりました。感謝です!
AutoPagerizeに対応する
- その後、will_paginateはバージョンアップを続け、rel="next"またはrel="prev"属性がデフォルトで設定されるようになった。
つまり、以下の作業は不要になったということです。
AutoPagerizeに対応するために、次ページリンクにrel='next'属性を設定したい。しかし、前ページ・次ページのリンクを直接生成しない仕様のwill_paginateでどうやって実現するか?悩んだ結果、ソースコードを以下のように直接修正してしまった...。
--- vendor/plugins/will_paginate/lib/will_paginate/view_helpers.rb +++ vendor/plugins/will_paginate~/lib/will_paginate/view_helpers.rb @@ -112,8 +112,8 @@ def to_html links = @options[:page_links] ? windowed_paginator : [] # previous/next buttons - links.unshift page_link_or_span(@collection.previous_page, 'disabled', @options[:prev_label]) - links.push page_link_or_span(@collection.next_page, 'disabled', @options[:next_label]) + links.unshift page_link_or_span(@collection.previous_page, 'disabled', @options[:prev_label], :rel=>'prev') + links.push page_link_or_span(@collection.next_page, 'disabled', @options[:next_label], :rel=>'next') html = links.join(@options[:separator]) @options[:container] ? @template.content_tag(:div, html, html_attributes) : html @@ -168,10 +168,10 @@ links end - def page_link_or_span(page, span_class = 'current', text = nil) + def page_link_or_span(page, span_class = 'current', text = nil, html_options = {}) text ||= page.to_s if page and page != current_page - @template.link_to text, url_options(page) + @template.link_to(text, url_options(page), html_options) else @template.content_tag :span, text, :class => span_class end
ところが、その後:rendererオプションがあることに気付く!:rendererオプションでページリンクを描画するクラスを指定するようになっている。デフォルトはWillPaginate::LinkRendererが設定されるらしい。それなら、WillPaginate::LinkRendererクラスを継承したLinkRendererWithRelクラスを作って、必要な修正を行えば良いはず。以下のようにやってみた。
- app/helpers/link_renderer_with_rel.rbファイルを新しく作成し、修正箇所の上記差分のメソッドだけコピーした。
# app/helpers/link_renderer_with_rel.rb class LinkRendererWithRel < WillPaginate::LinkRenderer def to_html links = @options[:page_links] ? windowed_paginator : [] # previous/next buttons links.unshift page_link_or_span(@collection.previous_page, 'disabled', @options[:prev_label], :rel=>'prev') links.push page_link_or_span(@collection.next_page, 'disabled', @options[:next_label], :rel=>'next') html = links.join(@options[:separator]) @options[:container] ? @template.content_tag(:div, html, html_attributes) : html end protected def page_link_or_span(page, span_class = 'current', text = nil, html_options = {}) text ||= page.to_s if page and page != current_page @template.link_to(text, url_options(page), html_options) else @template.content_tag :span, text, :class => span_class end end end
- will_paginateペルパメソッドで、:renderer=>LinkRendererWithRelを指定した。
<%= will_paginate @slips, :prev_label=>'«前', :next_label=>'次»', :renderer=>LinkRendererWithRel %>
これで、AutoPagerizeなwill_paginateになった!この方法なら、rel属性の追加だけでなく、will_paginateを自分仕様に自由に拡張できそうだ。複数のrendererを作っておき、ページに合わせて切り替えることも出来る。素晴らしい!