What is it, naokirin?

kaminari に入門して、ページネーションしよう

github.com

kaminari といえば、Rails などでページネーションするための gem です。

今回は Rails に導入してみて、ページネーションしてみることにします。

今回は Rails 5.2, kaminari 1.1.1 で行っています。

kaminari をインストールする

Rails プロジェクトを作成したら、Gemfile に gem kaminari を追加して、 bundle でインストールします。

確認用に User モデルを追加して、一覧表示するビューを作る

今回は確認用に User モデルを追加してみます。

$ bundle exec rails g User name:string age:integer

生成後、データベースの生成とマイグレーションを実行します。

$ bundle exec rails db:create db:migrate

この時点で一度、データを準備しておきます。

$ bundle exec rails c
Loading development environment (Rails 5.2.3)

>> User.new(name: 'Bob', age: 20).save

これで、1つだけ users テーブルに登録されている状態になります。

次にこのデータを一覧表示するためのコントローラーとビューを作ります。

$ bundle exec rails g controller Users index

kaminari を使ってみる

準備が整ったので、kaminari を利用したコントローラーおよびビューの実装をしてみます。

app/controller/users_controller.rb の index メソッドを以下のようにします。

def index
  @users = User.all.page(params[:page])  # 指定されたページのユーザーデータを取得する
end

app/views/users/index.html.erb

<h1>Users#index</h1>
<div>
  <%= paginate @users %>  <%# ← ページネーションのリンクを表示する %>
  <%= page_entries_info @users %> <%# ← ページネーションの現在の表示数/全体の数を表示する %>
</div>

<div>
  <table border="1">
    <tr>
      <td>ID</td>
      <td>Name</td>
      <td>Age</td>
      <td>Create at</td>
    </tr>
    <% @users.each do |user| %>
      <tr>
        <td><%= user.id %></td>
        <td><%= user.name %></td>
        <td><%= user.age %></td>
        <td><%= user.created_at %></td>
      </tr>
    <% end %>
  </table>
</div>

開発用にサーバーを起動して、 http://localhost:3000/users/index にアクセスすると、以下のように表示されます。

f:id:naokirin:20190402185529p:plain:w400

これだけではデータが少なくてわかりにくいので、データを増やしてみましょう。

bundle exec rails c
Loading development environment (Rails 5.2.3)

>> 100.times { |n| User.new(name: "num: #{n}", age: n).save }

これで再度、ページを表示してみましょう。

f:id:naokirin:20190402190159p:plain:w400

以下のように、25ずつ表示されるようになり、ページネーションのリンクも表示されていることを確認できます。

ページネーションの挙動についてもう少し見てみる

ページを kaminari のヘルパーで生成される以外で指定したいとき

先程のページで2ページ目以降に行くと、URLが /users/index?page=2 のようになっています。

このようにリクエストされることで params[:page] で何ページ目か取得できるようになっています。また、1ページ目のみ、 nil でも良いことになっているため、この指定がついていません。

kaminari のヘルパーメソッドを使わずに特定のページへ飛ぶときには、このようなURLによる指定ができます。

表示件数を変更したいとき

1ページあたりの件数が25件では多いや、少ないといったこともあるでしょう。

この場合、概ね3つの方法で変更ができます。

1つ目は、データ取得時に per メソッドで指定する方法です。

@users = User.all.page(params[:page]).per(10)

2つ目は、モデルで指定する方法です。これは1つ目が指定されていないときに有効になります。

class User < ApplicationRecord
  paginates_per 15
...

最後に kaminari の設定ファイルを生成して、アプリケーション全体のデフォルト設定として適用できます。

設定ファイルの生成は、 bundle exec rails g kaminari:config で、 config/initializers/kaminari_config.rb に生成されます。

そこで以下のように設定することで適用できます。

# frozen_string_literal: true
Kaminari.configure do |config|
  config.default_per_page = 20
...
end

ページリンク表示時の挙動の変更

リンク表示時に例えば 1 2 ... 5 6 7 8 9 ... 11 12 のように、端をいくつかと現在のページ周辺を表示するようにしたいというのもあるかと思います。

その場合 window , outer_window を指定することで達成できます。

index.html.erbpaginate 部分を以下のように書き換えます。

<%= paginate @users, window: 2, outer_window: 2 %>

また確認しやすいように、 UsersController#index の実装は @users = User.all.page(params[:page]).per(5) としておきましょう。

すると以下のような表示になることを確認できます。

f:id:naokirin:20190402192958p:plain:w400

日本語表示する

これまでは英語表示していたので、日本語表示しましょう。

kaminari 自体では日本語翻訳ファイルは対応していないので、自身で作る必要があります。

config/locales/kaminari_ja.yml を作成して、以下を記述します。

ja:
  views:
    pagination:
      first: "&laquo; 最初"
      last: "最後 &raquo;"
      previous: "&lsaquo; 前"
      next: "次 &rsaquo;"
      truncate: "&hellip;"
  helpers:
    page_entries_info:
      one_page:
        display_entries:
          zero: "%{entry_name} が存在しません"
          one: "<b>1</b> 件の %{entry_name} を表示"
          other: "<b>%{count}</b> 件の %{entry_name} を表示"
      more_pages:
        display_entries: "<b>%{total}</b> 件中 <b>%{first}&nbsp;-&nbsp;%{last}</b> 件の %{entry_name} を表示"

これでページを開きなおすと、以下のように日本語で表示されることを確認できます。

f:id:naokirin:20190402195223p:plain:w400

まとめ

kaminari を利用すると、簡単にページネーション機能を追加できるのでよく利用されていると思います。

ただ一度設定すると触らないことが多いので、今回は入門記事を書いてみることにしました。

今回は表示を切り替えたりといった部分を書いていないので、実際の利用時はそのあたりも必要になるかと思いますが、本家のGitHubの説明が非常にわかりやすいので、そのあたりから必要なものを拾っていくことで達成できるかと思います。