【Rails】ページネーションを「Pagy」で導入する
Pagyを使う理由
Railsアプリにページネーションを導入する際、長くwill_paginationやkaminariが使われてきており、定番となっているのは言うまでもないですね。
2018年11月に登場し、定番たちの間に割って入ろうとしているのがPagyです。Pagyの利点は次のサイトで熱く語られております。
- Rails:「Pagy」gemでRailsアプリを高速ページネーション(翻訳)
https://techracho.bpsinc.jp/hachi8833/2018_06_05/57481
要約すると、定番よりもメモリ使用量が少なく、使い勝手もいいということです。
導入方法
ここから、あくまで私が試した方法を記します。(よりスマートな方法がある場合は教えて下さい。)
gem 'pagy'
からのbundle install
して下さい。
その後、少しだけ設定を書く必要がありますが、こちらのQiitaがわかりやすいです。
- Railsでpagyを使ったページネーション
https://qiita.com/white0221/items/d5a0386882943131df77
そのままではエラーになった
class UsersController < ApplicationController include Pagy::Backend def index user_hash = Record.group(:user_id).maximum(:created_at) user_list = user_hash.sort_by{ |k, v| v }.reverse.to_h.keys @pagy, @users = pagy(User.find(user_list)) end
上記コードはNoMethodErrorとなりました。
一見エラーになりそうではないのですが、どうもpagyの引数はActiveRecord::Relationクラスに属している必要があるようで、上記のように配列を引数としてしまうとエラーになります。
ActiveRecord::Relationクラスにするにはall
やwhere
の結果を入れる必要ありです。
引数が配列の場合は変換しよう
# 抜粋して再掲 @pagy, @users = pagy(User.find(user_list))
実は私のケースではuser_listは、user_idが入ったリストなので大層な変換は必要ありませんでした。
# 修正後 @pagy, @users = pagy(User.where(id: user_list))
find
をwhere
に取り替えただけです。 デザインは置いておいてエラーなく実装できました。
しかし、多くの人が引っかかるのはモデルからmap
やselect
等でのメソッドでデータを取得しエラーになるパターンでは無いかと思います。
# User.allではActiveRecord_Relationとなる irb(main):001:0> User.all.class => User::ActiveRecord_Relation # mapメソッドを使うとArrayクラスになってしまう irb(main):002:0> User.all.map{|user| user}.class 〜 User Load (2.5ms) SELECT `users`.* FROM `users` => Array
ということです。 なので, Pagyを使う時はmap等は直接使わずにwhere等の中で使って下さい。
#例えばこんな感じ User.where( id: [配列].map{ |user| user.id } )
(参考にさせて頂いた文献)
- 配列をActiveRecord::Relationで再取得するメソッドを作ってみる
https://qiita.com/shibadai/items/ddbc76a8b980cd8354bc - NoMethodError | undefined method `offset' for #<Array:*> | Pagy https://v-crn.hatenablog.com/entry/2019/08/29/NoMethodError%7C_undefined_method%60offset%27_for%23%3CArray%3A%2A%2A%2A%3E%7C_Pagy