Help us understand the problem. What is going on with this article?

will_paginateのurlを変更する

More than 1 year has passed since last update.

発生した問題

will_paginateをrailsアプリに組み込んでいるが、paramsを用いた検索を併用すると・・・2ページ目以降のurlがおかしい?

例えば、/search/myloversというページでparamsを用いたDB検索を行う。そのとき、発行されるurlは、
 /search/mylovers?age_gte=20&age_lte=25&occupation=model
といった感じになる。しかし、このとき、will_paginateを用いて複数ページに結果を分割していたとして、will_paginateが作成する「次へ」ボタンのurlは、
 /search/mylovers?age_gte=20&age_lte=25&occupation=model&page=2
とはならないときがある。

原因

url_forヘルパーがroute.rbの設定に依存すること

will_paginateはurl_forヘルパーを用いてurlを作成し、それをボタンに埋め込む。しかし、もしrails側のroutes.rbにおいて、
 get search/mylovers/:occupation => search/index
みたいな設定をしていた場合(つまり、params[:occupation]をurl内に組み込んでいた場合)、url_forヘルパーは、
 /search/mylovers?age_gte=20&age_lte=25&occupation=model
のかわりに、
 /search/mylovers/model?age_gte=20&age_lte=25
を返してくる。つまり、routes.rbでの設定を逆に解釈する。routes.rbでは、「もし、/search/myloversの後ろになんかひっついてきたら、それをparams[:occupation]として解釈してね」という指示を与えたつもりが、url_forヘルパーは気を回して「もし、params[:occupation]が渡ってきたら、search/mylovers/の後ろに引っ付けるようにしよう」としてしまう。

 基本的にはそれでも問題ない場合が多いが、例えば、params[:occupation]が配列形式である場合には、このurl_forヘルパーは壊れる。
 /search/mylovers?occupation=model&occupation=nurse
というurlを発行すると、url_forヘルパーは、
 /search/mylovers/modelnurse
を返してくる。もちろんこれは無効urlとなり、ページネーションが動作しないことになる。

解決策

 will_paginate内で作られるurlに問題があるので、gemのオーバーライドをする。オーバーライドとは、既存のメソッドの上書きのようなもの。オーバーライドのやり方は以下のステップ。

  • 上書き用のファイルを用意
  • 上書きするメソッドの位置を特定
  • 上書き内容を書く

 今回は、app/helper内にファイルを用意した。次に、gem内部のどのメソッドを修正したいか(するべきか)を特定する。今回の場合、発行されるurlを変更したいので、urlを作成しているメソッドを探す。見つけたら、書き換えるメソッドのある場所を、module名::class名で指定する。今回はmoduleがネストしていたので、WillPaginate::ActionView::LinkRenderer。書き換えるメソッド名は「url(page)」。ここまでの段階で、上書きファイルの内容は下のようになる。

paginatehelper.rb
module PaginationHelper
 class SearchPagination < WillPaginate::ActionView::LinkRenderer
  def url(page)#書き換えるメソッドと同じ名前に
    #処理
  end
 end
end

あとは、処理の中で好きに書けば良い。今回はrequest.full_pathを使って現在のurlを取得し、お尻にparams[:page]をつける処理にした。

あとは、viewのwill_paginateのrendererオプションにオーバーライドしたいやつを指定。

index.html.erb
<%= will_paginate @mylovers, renderer: PaginationHelper::SearchPagination

これで完了。will_paginateはrendererオプションでオーバーライドして色々カスタマイズができる。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした