pagination_links_remoteを作ってみる。
Ajaxを利用して、リスト表示の並べ替えや検索を処理するようにしたため、pagination_linksを使えない状態だった。並べ替えや検索で表示条件をアレンジしても、ページ番号をクリックすると、保持していた表示条件がリセットされてしまうのだ。
表示条件を保持するためには、ページ番号のリンクをクリックした時に、条件を保持しているフォームも送信する必要がある。つまり、pagination_linksで生成されるページ番号に、link_to_remoteが作り出す機能を与えたい。How to Paginate With Ajaxのページを参考に、以下のようにやってみた。(上記ページで紹介されている一番最後のパターンでやってみた。)
app/helpers/application_helper.rbへの追記
# Methods added to this helper will be available to all templates in the application. module ApplicationHelper include LoginEngine include UserEngine end # 以下pagination_links_remoteの追記 module ActionView module Helpers module PaginationHelper def pagination_links_remote(paginator, options={}, html_options={}) name = options[:name] || DEFAULT_OPTIONS[:name] #params = (options[:params] || DEFAULT_OPTIONS[:params]).clone pagination_links_each(paginator, options) do |n| options[:url][name] = n link_to_remote(n.to_s, options, html_options) end end end # PaginationHelper end # Helpers end # ActionView
- pagination_linksのソースとほとんど一緒だ。
- do...endブロック内が、pagination_links_remoteのために置き換えたコード。
- デフォルト値は以下。
DEFAULT_OPTIONS = { :name => :page, :window_size => 2, :always_show_anchors => true, :link_to_current_page => false, :params => {} }
-
-
- module ActionView、module Helpers、module PaginationHelperのように、三重にネストするコードの意味が知りたい...。
-
app/views/softwares/list.rhtmlへの追記
<%= pagination_links_remote @software_pages, :update => "list_update", :submit => "store", :url => {:action => 'list_update'} %>
- ビューでpagination_links_remoteを実際に利用すると、上記のような書式になる。
- link_to_remoteと似たような書式だけど、urlのオプションはアクションまで。それ以下のページはpagination_links_remoteが設定してくれるから。
すべての流れを理解してないが、なんとかpagination_links_remoteもどきが出来た!
-
-
- 以下は、自分でpagination_linksのソースを読んだ時のコメント
-
# 全9ページの表示例(デフォルトオプションのままで、現在のページは5) # 1 ... 3 4 5 6 7 ... 9 # # 以下デフォルトオプションのキーの意味 # :name ページを表現するパラメーター名 # :window_size 前後のページを表示する範囲(もし1なら 1 ... 4 5 6 ... 9 と表示される) # :always_show_anchors 最初と最後のページを常に表示するかどうか?(もしfalseなら 3 4 5 6 7 と表示される) # :link_to_current_page 現在のページにリンクを設定するかどうか? # :params その他のパラメーター module ActionView module Helpers module PaginationHelper # デフォルトオプションの定義 unless const_defined?(:DEFAULT_OPTIONS) DEFAULT_OPTIONS = { :name => :page, :window_size => 2, :always_show_anchors => true, :link_to_current_page => false, :params => {} } end def pagination_links(paginator, options={}, html_options={}) name = options[:name] || DEFAULT_OPTIONS[:name] params = (options[:params] || DEFAULT_OPTIONS[:params]).clone pagination_links_each(paginator, options) do |n| params[name] = n link_to(n.to_s, params, html_options) end end # pagination_linksでは、do...endブロックをpagination_links_eachに渡して処理する。 # pagination_links_eachでは、yieldの部分で上記do...endブロックを実行する。 # yield(引数)の部分は、以下のコードに置き換えられる。 # params[:page] = 引数 # link_to(n.to_s, params, html_options) # link_toをlink_to_remoteに置き換えれば、pagination_links_remoteができるかも...。 def pagination_links_each(paginator, options) ### 利用する変数を準備する # オプションにデフォルトを加える options = DEFAULT_OPTIONS.merge(options) # 現在のページにリンクを設定するかどうか? link_to_current_page = options[:link_to_current_page] # 最初と最後のページを常に表示するかどうか? always_show_anchors = options[:always_show_anchors] # 現在のページ current_page = paginator.current_page # ページ番号として表示するpaginatorオブジェクトの配列(3 4 5 6 7のページ配列) window_pages = current_page.window(options[:window_size]).pages # 1ページ以下の場合の処理 return if window_pages.length <= 1 unless link_to_current_page # 最初と最後のページを取得 first, last = paginator.first, paginator.last ### 以下で実際に 1 ... 3 4 5 6 7 ... 9 のリンクの集合を作る ### 3つのパートに分けて処理している # 「1 ... 」の部分を生成 html = '' if always_show_anchors and not (wp_first = window_pages[0]).first? html << yield(first.number) # 上記yieldを実際に置き換えると、以下と同等 # html << link_to(first.number.to_s, :page=>first.number, html_options) html << ' ... ' if wp_first.number - first.number > 1 html << ' ' end # 「3 4 5 6 7」の部分を生成 window_pages.each do |page| if current_page == page && !link_to_current_page html << page.number.to_s else html << yield(page.number) # 上記yieldを実際に置き換えると、以下と同等 # html << link_to(page.number.to_s, :page=>page.number, html_options) end html << ' ' end # 「 ... 9」の部分を生成 if always_show_anchors and not (wp_last = window_pages[-1]).last? html << ' ... ' if last.number - wp_last.number > 1 html << yield(last.number) # 上記yieldを実際に置き換えると、以下と同等 # html << link_to(last.number.to_s, :page=>last.number, html_options) end html end end # PaginationHelper end # Helpers end # ActionView