【Rails】でページネーションをgemで実装!~kaminariのキホンのキ~

Ruby on Rails

どうも、フリーランスエンジニアのウェブ系ウシジマくんです!

今回の記事では、Railsでページネーションを気軽に実装できるkaminariというgemについて取り上げていきます。

公式リポジトリ

GitHub - kaminari/kaminari: ⚡ A Scope & Engine based, clean, powerful, customizable and sophisticated paginator for Ruby webapps
⚡ A Scope & Engine based, clean, powerful, customizable and sophisticated paginator for Ruby webapps - kaminari/kaminari

ページネーションというのは、検索結果や商品一覧ページを表示した際にページを分割することでアクセスしやすくする機能。

ページネーションのイメージ画像

ボタンを押すことで、本でいうところのページを1枚1枚めくっていくようなものだと理解してもらえたらわかりやすいかな。

今回の記事の対象者

  • kaminariでページネーションを実装する方法について学びたい人
  • kaminariの内部構造について知りたい人

Gemfileにkaminariを追加する

以下のような感じで、プロジェクト配下にあるGemfileにkaminariを追加しましょう。

(中略)
gem 'rake', '< 11.0'
gem 'foreigner', '~> 1.6.1'
gem 'kaminari', '~> 0.15.1' # ページネーション

ちなみに、** ~> 0.15.1 ** というのは、バージョンを指定の表記方法です。

この記述により、メインアップデートではなくマイナーアップデートのみ許可することになります。

参考

301 Moved Permanently

bin/bundleを実行

RailsチュートリアルやProgateでもお馴染みですよね。Gemfileに何かを追加したら必ず実行しましょう。

bin/bundle
# bin/bundle installでもOK、

bin/rails g kaminari:configを実行

この記述によって、kaminariの設定ファイルが自動でインストールされます。

bin/rails g kaminari:config

インストールされるファイル構造は次の通り。

config/
|--initializers
|  |--kaminari_config.rb

bin/rails g kaminari:views defaultを実行

bin/rails g kaminari:views default

こちらのインストールされるファイル構造は次の通り。

app/views
|--kaminari
|  |--_first_page.html.erb
|  |--_gap.html.erb
|  |--_last_page.html.erb
|  |--_next_page.html.erb
|  |--_page.html.erb
|  |--_paginator.html.erb
|  |--_prev_page.html.erb

ページそれぞれに_(アンダースコア)がついているのは、全て部分テンプレートだからですね。

実行することでページネーションをviewで表示するためのERBテンプレートを生成します。

config/initializers/kaminari_config.rbを以下のように変更

kaminari_config.rb をいじることで色々と設定をカスタマイズすることができます。

ここでは、1ページに表示する項目数のデフォルト値を10に変更しています。

Kaminari.configure do |config|
  config.default_per_page = 10 # 1ページに表示する項目数のデフォルト値を10に変更
  # config.default_per_page = 25
  # config.max_per_page = nil
  # config.window = 4
  # config.outer_window = 0
  # config.left = 0
  # config.right = 0
  # config.page_method_name = :page
  # config.param_name = :page
end

それぞれの項目の意味については、素晴らしいサイトがあったので引用させていただきました。

  • default_per_page
    デフォルトのページあたりの表示件数(デフォルトは 25)。
  • max_per_page
    ページあたりの表示件数の最大(デフォルトは nil、つまり無制限)。
  • window
    表示中のページの左右何ページ分のリンクを表示するかを指定します(デフォルトは 4)。上記画像はデフォルトの 4 で、11 ページを表示しているところです。11 の左右それぞれ 4 ページ分のリンクが生成されています。
  • outer_window
    先頭ページ、及び最終ページから何ページ分のリンクを表示するかを指定します(デフォルトは 0)。left、right が指定された場合は、そちらの値が優先されます。
  • left
    先頭ページから何ページ分のリンクを表示するかを指定します(デフォルトは 0)。上記画像は 3 を指定した場合です。
  • right最終ページから何ページ分のリンクを表示するかを指定します(デフォルトは 0)。上記画像は 2 を指定した場合です。
  • page_method_name
    モデルに追加されるページ番号を指定するスコープの名前(デフォルトは page)。
  • param_name
    ページ番号を渡すために使用するリクエストパラメータの名前(デフォルトは page)。
    引用: Railsライブラリ紹介: ページングを行う「kaminari」

config/locales/views/paginate.ja.ymlに以下を記述。

config/locales/views/paginate.ja.ymlがなければ新規作成しましょう。ここでの設定はerbテンプレートで使用するラベルを日本語化ためのもの。

記述する際には、インデントに注意。なぜなら、インデントがおかしいと設定ファイルが読み込まれません。

:(セミコロン)と””(ダブルクオート)で囲った文字列の間には、半角スペースが2個分必要なので注意しましょう。


ja: views: pagination: first: "先頭" last: "末尾" previous: "前" next: "次" truncate: "..."

Railsアプリケーションを再起動する。

ここまで設定できたら、一旦PumaやWEBrickで起動しているアプリケーションサーバーを再起動しましょう。

config/initializeディレクトリ配下のファイルを書き換えたり、config/localesディレクトリ配下に新規ファイルを作成したら、Railsアプリケーションを再起動しないと読み込まれないので。

ページネーションを実装したいアクションを持つcontrollerにpageメソッドを定義

@events = @events.page(params[:page])

Pageメソッドは引数に指定した整数をページ番号とみなして、内部ではSQLのLIMITとOFFSETを発行しています。

# bin/rails c —sandbox
irb(main):025:0> @events.page(1)
  StaffEvent Load (1.2ms)  SELECT  `staff_events`.* FROM `staff_events`  WHERE `staff_events`.`staff_member_id` = 2  ORDER BY `staff_events`.`created_at` DESC LIMIT 10 OFFSET 0

irb(main):026:0> @events.page(2)
  StaffEvent Load (0.9ms)  SELECT  `staff_events`.* FROM `staff_events`  WHERE `staff_events`.`staff_member_id` = 2  ORDER BY `staff_events`.`created_at` DESC LIMIT 10 OFFSET 10

これにより、configで指定した表示件数に応じた絞り込みを行っています。

参考

https://doruby.jp/users/whale/entries/ActiveRecord–Relation%E3%81%A8%E3%81%AF%E4%B8%80%E4%BD%93%E3%81%AA%E3%82%93%E3%81%AA%E3%81%AE%E3%81%8B
OFFSETを使わない高速なページネーションの実現 - Qiita
概要SQLでページネーションと言えばこんな処理が定番かと思われますが…SELECT * FROM samples ORDER BY id LIMIT 5 OFFSET 30 SELECT * F…

ページネーションを実装したい箇所にpaginateメソッドを追記する。

paginateメソッドはkaminariで提供されるヘルパーメソッド。pageメソッド実行済みのRelationオブジェクトを受けとり、その位置にページネーションのためのリンクの列を生成します。

# ページネーションしたい情報の入ったインスタンス変数: User.allなど
<%= paginate @user %>

最後に

今回はkaminariのキホンのキということで、ページネーションを実装するに当たってスタンダードの部分について触れました。

公式リポジトリは英語ですが、コードが書いてあるので、コピペしつつカスタマイズしていけばそんなに難しくないと思います。

GitHub - kaminari/kaminari: ⚡ A Scope & Engine based, clean, powerful, customizable and sophisticated paginator for Ruby webapps
⚡ A Scope & Engine based, clean, powerful, customizable and sophisticated paginator for Ruby webapps - kaminari/kaminari

それでは楽しいRailsライフを!

ちょっとしたつぶやき

最近ドットインストールでエンジニアのためのsketch入門を受講しました。

めちゃくちゃわかりやすくて、この動画のレッスン内容を応用すれば、ブログのバナーくらいは簡単にできるようになるのでおすすめです!

エンジニアのためのSketch入門 (全30回) - プログラミングならドットインストール
macOS用のUIデザインツールであるSketchについて見ていきます。