Rails2.0からページネーションがプラグインベースになりました。普通のページネーションであれば、

@memos = @user.memos.paginate(:page => params[:page], :per_page => 10, :o rder=>”memos.id DESC”)

だけで使えるようになって便利ですが、任意の情報に対してページネーションする方法がいまいち分かっていませんでした。そして、acts_as_searchableを使って、HyperEstraierで全文検索を行う際に、ページネーションをどのように行えば良いのか調べつつ分かったところを書いてみたいと思います。

実際にページネーション処理を行っているのは、

vendor/plugins/will_paginate/lib/will_paginate/finder.rb

になります。ここの

def paginate_by_sql(sql, options)
  WillPaginate::Collection.create(*wp_parse_options!(options)) do |pager|
    query = sanitize_sql(sql)
    options.update :o ffset => pager.offset, :limit => pager.per_page

    original_query = query.dup
    add_limit! query, options
    # perfom the find
    pager.replace find_by_sql(query)

    unless pager.total_entries
      count_query = original_query.sub /bORDERs+BYs+[w`,s]+$/mi, ''
      count_query = "SELECT COUNT(*) FROM (#{count_query}) AS count_table"
      # perform the count query
      pager.total_entries = count_by_sql(count_query)
    end
  end
end

が参考になります。

pager.replaceに、リストを入れて、pager.total_entriesに行数を入れればOKのようです。この処理をまねて、

app/controllers/application.rb

に次のように定義します。

module WillPaginate
  module Finder
    module ClassMethods
      def paginate_by_fulltext_search(query, options)
        WillPaginate::Collection.create(*wp_parse_options!(options)) do |pager|
          pager.replace fulltext_search(query, options)

          count_options = Hash.new
          count_options[:count] = true
          count_options[:attributes] = options[:attributes] if options[:attributes]
          pager.total_entries = fulltext_search(query, count_options)
        end
      end
    end
  end
end

です。そして、呼び出し側では次のようにします。

@memos = Memo.paginate_by_fulltext_search(params[:q], :attributes => “user_id NUMEQ %d” % @user.id, :limit => perpage, :o ffset => offset, :page => params[:page], :per_page => perpage)

ここで、:limitはacts_as_searchable用、:per_pageはwill_paginate用になります。:pageや:offsetは共通で利用できるようです。:attributesはあれば設定します。これさえ設定しておけば、ビュー側は

<%= will_paginate @memos, :prev_label=> _(’« Prev’), :next_label=> _(’Next »’) %>

が利用できて便利です。ちなみにpaginate_by_sqlではoptionsがアップデートされるので、デフォルトの30件になってしまうようですね。これはなぜなんだろう…。

Leave a Reply

MOONGIFTネットワーク。こちらもぜひご覧ください。
MOONGIFT

Warning: array_slice() [function.array-slice]: The first argument should be an array in /virtual/producing/public_html/producing-web.com/wp-content/themes/network.php on line 15
  • No items
Open Service
Rails 2.0
Resident on Net
iPhone最適化
リーンソフトウェア
MarketPedia
Producing Web
Cool Coding