1
1

【Rails】gem 'kaminari' と Tailwind CSS + daisyUI でページネーションをカスタマイズする

Posted at

はじめに

こんにちは、ゆうき(@yuki31100725)と申します。
現在、プログラミングスクールに通ってRuby on Railsを学習しております。

私はプログラミング学習中で、初学者です。
内容に誤りのある場合がございます。
もし間違いがあればご指摘いただけますと幸いです。

記事の概要

gem 'kaminari'を導入してページネーションを実装した際、導入済みだったTailwind CSS (+ daisyUI)を用いてレイアウト調整を試みました。

本記事では、実装例とともにレイアウト調整の手順についてご紹介できればと思います。

記事のゴール

gem 'kaminari'でページネーション実装後、Tailwind CSS (+ daisyUI)を用いて下記のようなレイアウトにすることを目標としています。

【レイアウト調整前】
Image from Gyazo

【レイアウト調整後】
Image from Gyazo

背景

gem 'kaminari'は、CSSフレームワークのbootstrapと併せて使用することで簡単にレイアウト調整できるため、下の記事のように関連記事が幾つか散見されます。

一方、Tailwind CSSを使用している場合の実装例を書かれている記事は見当たらなく、私自身実装に少々時間がかかったため記事執筆に至りました。

環境

  • Rails 7.1.3.4
  • Ruby 3.2.3
  • Tailwind CSS 3.4.7
  • daisyUI 4.12.10

当該記事は、Tailwind CSS、daisyUIの導入手順までは含みませんので、既に導入済みの状態で見て頂けると幸いです。

また、bootstrapやTailwind CSS (+ daisyUI)未導入であっても、下記のような流れでレイアウト調整できるため、途中まではご参考になるかと思います。

  1. gem 'kaminari' におけるビューのカスタムテンプレートを導入
  2. ページネーションの見た目をCSSで整える

ページネーションとgem 'kaminari'について

ページネーションについて

ページネーションとは、大量のデータを複数のページに分割して表示する技術を指します。
この技術を使用することで、ページの読み込み時間を短縮することが可能になります。
下の画像はGoogleの検索結果画面でよく見るページネーションのデザインになります。

Image from Gyazo

gem 'kaminari'について

gem 'kaminari'はページネーションを簡単に実装するためのgemです。

実装手順

手順概要

  1. ページネーションの導入
    1.1. kaminariをGemfileに追加する
    1.2. 設定ファイルを生成し、初期設定を変更する
    1.3. コントローラーの記述を修正する
    1.4. ビューの設定を記述する

  2. ページネーションのカスタマイズ
    2.1. kaminariにおけるビューのカスタムテンプレートを導入
    2.2. カスタムテンプレートの中身を見てみる
    2.3. Tailwind CSS適用と必要なテンプレートの選定
    2.4. daisyUIのコンポーネントを利用する
    2.5. ページ数の表示制限
    2.6. 表記をカスタマイズする

手順詳細

1. ページネーションの導入

1.1 kaminariをGemfileに追加する

以下の通り、Gemfileにkaminariを追加します。

gem 'kaminari'

以下のコマンドを実行してインストールします。

bundle install

1.2 設定ファイルを生成し、初期設定を変更する

設定ファイルを生成するため、以下のコマンドを実行します。

rails g kaminari:config

コマンド実行後、config/initializersディレクトリに生成されるkaminari_config.rbを開きます。
ここでは、アプリにおいてデフォルトで使用したい1ページあたりのレコード数を設定します。
最初に25が記入されているかと思いますが、私はここを5にしました。

config/initializers/kaminari_config.rb
  Kaminari.configure do |config|
    config.default_per_page = 5 # 1ページあたりの表示件数
  end

1.3. コントローラーの記述を修正する

ページネーションを利用したいデータの取得を担っているコントローラーの記述を修正します。
私の場合は、施設の情報一覧を取得するspotsコントローラーのindexアクションに適用してみました。

app/controllers/spots_controller.rb
class SpotsController < ApplicationController
  def index
-    @spots = Spot.all
+    @spots = Spot.all.page(params[:page])
  end
end
pageメソッド ページネーションにおけるページ数を指定

なお、以下のようにperメソッドを用いることでページネーションの設定を上書きすることも可能です。

# 1ページごとのデータ数を10に変更
@spots = Spot.all.page(params[:page]).per(10)
perメソッド 1ページあたりに表示する件数を指定

1.4. ビューの設定を記述する

index.html.erb内のページネーションを表示させたい箇所に、paginateヘルパーを用いて下記のように記述します。

app/views/spots/index.html.erb
<%= paginate @spots %>

これにより、下の画像のようなページネーションが作成されるかと思います(若干異なる可能性もあります)。

Image from Gyazo

ここまでで、最低限のページネーションの機能ができました。

2. ページネーションのカスタマイズ

2.1. kaminariにおけるビューのカスタムテンプレートを導入

ページネーションのレイアウト調整をする際、kaminari用のビューのカスタムテンプレートを導入します。
ターミナルで下記のコマンドを実行します。

rails g kaminari:views default
bootstrapを使っている場合 bootstrapには専用のカスタムテンプレートが用意されているようです(実行するコマンドが若干異なります)。 関係する資料をこちらに記載しておきますので、必要に応じてご確認ください。

https://qiita.com/rio_threehouse/items/313824b90a31268b0074
https://pikawaka.com/rails/kaminari

また、gemを新たに導入することで、カスタムテンプレートを使用せず簡単にレイアウト調整ができるということで、その場合の実装例が書かれた資料もこちらに記載しておきます。

https://zenn.dev/yukihaga/articles/3d49208638e397

2.2. カスタムテンプレートの中身を見てみる

先ほどのコマンドを実行すると、app/views/kaminari/配下にカスタムテンプレートが7ファイル生成されます。
以下は、各ファイルの記述(デフォルト)と役割の説明です。必要なければ読み飛ばしてください。

app/views/kaminari/_paginator.html.erb 他のテンプレートファイルを読み込むための骨格となるテンプレートファイルです。 説明のため、こちらで適宜コメントを入れています。
<%= paginator.render do -%>
  <nav class="pagination" role="navigation" aria-label="pager">
    <%# 現在のページが最初のページでない場合のみ「最初のページ」と「前のページ」へのリンクを表示 %>
    <%= first_page_tag unless current_page.first? %>
    <%= prev_page_tag unless current_page.first? %>
 
    <% each_page do |page| -%>
     <%# 表示すべきページ番号の場合true %>
      <% if page.display_tag? -%>
        <%# page_tagヘルパーでそのページへのリンクを生成 %>
        <%= page_tag page %>
     <%# 表示すべきページ番号ではない場合 → 複数ページが連続して省略されている場合(省略記号 “…” などを表示する必要がある場合)にtrue %>
      <% elsif !page.was_truncated? -%>
        <%# ページ番号の間に省略記号(”…”, “…“など)を表示するためのタグ %>
        <%= gap_tag %>
      <% end -%>
    <% end -%>

    <%# 現在のページが最後のページでない場合のみ「次のページ」と「最後のページ」へのリンクを表示 %>
    <% unless current_page.out_of_range? %>
      <%= next_page_tag unless current_page.last? %>
      <%= last_page_tag unless current_page.last? %>
    <% end %>
  </nav>
<% end -%>
app/views/kaminari/_first_page.html.erb 「最初のページ」へのリンクを作るテンプレートです。
<span class="first">
  <%= link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, remote: remote %>
</span>
app/views/kaminari/_prev_page.html.erb 「前のページ」へのリンクを作るテンプレートです。
<span class="prev">
  <%= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, rel: 'prev', remote: true %>
</span>
app/views/kaminari/_page.html.erb 「1」「2」「3」などの各ページに対応するテンプレートです。
<span class="page<%= ' current' if page.current? %>">
  <%= link_to_unless page.current?, page, url, {remote: remote, rel: page.rel} %>
</span>
app/views/kaminari/_gap.html.erb ページネーションでページ番号が省略された箇所に「…」などの省略記号を表示するためのテンプレートです。
<span class="page gap"><%= t('views.pagination.truncate').html_safe %></span>
app/views/kaminari/_next_page.html.erb 「次のページ」へのリンクを作るテンプレートです。
<span class="next">
  <%= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, rel: 'next', remote: true %>
</span>
app/views/kaminari/_last_page.html.erb 「最後のページ」へのリンクを作るテンプレートです。
<span class="last">
  <%= link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, remote: remote %>
</span>

2.3. Tailwind CSS適用と必要なテンプレートの選定

ここはお好みの設定になります。
Tailwind CSSのサイトのリンクは下記になります。

ページネーション全体にレイアウトを適用する場合、app/views/kaminari/_paginator.html.erbでレイアウト調整をします。

app/views/kaminari/_paginator.html.erb
+ <div class="text-xs mt-8 mx-auto flex justify-center">
  <%= paginator.render do %>
    <nav class="pagination" role="navigation" aria-label="pager">
      <%# 現在のページが最初のページでない場合のみ「最初のページ」と「前のページ」へのリンクを表示 %>
-     <%= first_page_tag unless current_page.first? %>
      <%= prev_page_tag unless current_page.first? %>

      <% each_page do |page| %>
        <%# 表示すべきページ番号の場合true %>
        <% if page.display_tag? %>
          <%# page_tagメソッドでそのページへのリンクを生成 %>
          <%= page_tag page %>
-       <%# 表示すべきページ番号ではない場合 → 複数ページが連続して省略されている場合(省略記号 “…” などを表示する必要がある場合)にtrue %>
-       <% elsif !page.was_truncated? %>
-         <%# ページ番号の間に省略記号(”…”, “…“など)を表示するためのタグ %>
-         <%= gap_tag %>
        <% end %>
      <% end %>

      <%# 現在のページが最後のページでない場合のみ「次のページ」と「最後のページ」へのリンクを表示 %>
      <% unless current_page.out_of_range? %>
        <%= next_page_tag unless current_page.last? %>
-       <%= last_page_tag unless current_page.last? %>
      <% end %>
    </nav>
  <% end %>
+ </div>

今回私の実装では、ページネーション全体にTailwind CSSのclassを割り当てたかった(ページネーション全体の配置を調整するなど)ため、そのためのdivタグを追加しています。
また、私の場合、「最初のページ」「ページの省略を表す部分」「最後のページ」が不要だったため、読み込む部分の記述を削除しています。

2.4. daisyUIのコンポーネントを利用する

daisyUIを利用してレイアウトを簡単に調整します。
daisyUIにおけるページネーションのコンポーネントはこちらから確認できます。

今回、こちらのコンポーネントを参考に実装しました。
Image from Gyazo
Image from Gyazo

app/views/kaminari/_paginator.html.erb
- <div class="text-xs mt-8 mx-auto flex justify-center">
+ <div class="join text-xs mt-8 mx-auto flex justify-center">
  <%= paginator.render do %>
    <nav class="pagination" role="navigation" aria-label="pager">
      <%# 現在のページが最初のページでない場合のみ「最初のページ」と「前のページ」へのリンクを表示 %>
      <%= prev_page_tag unless current_page.first? %>

      <% each_page do |page| %>
        <%# 表示すべきページ番号の場合true %>
        <% if page.display_tag? %>
          <%# page_tagメソッドでそのページへのリンクを生成 %>
          <%= page_tag page %>
        <% end %>
      <% end %>

      <%# 現在のページが最後のページでない場合のみ「次のページ」と「最後のページ」へのリンクを表示 %>
      <% unless current_page.out_of_range? %>
        <%= next_page_tag unless current_page.last? %>
      <% end %>
    </nav>
  <% end %>
</div>
app/views/kaminari/_prev_page.html.erb class属性を追加します。
<span class="prev">
-  <%= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, rel: 'prev', remote: true %>
+  <%= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, class: "join-item btn", rel: 'prev', remote: true %>  
</span>
app/views/kaminari/_page.html.erb 現在見ているページであれば、"btn-active"となるようにclass属性を追加します。
- <span class="page<%= ' current' if page.current? %>">
-  <%= link_to_unless page.current?, page, url, {remote: remote, rel: page.rel} %>
-</span>
+ <%= link_to page, url, class: "join-item btn #{'btn-active' if page.current?}", remote: true, rel: page.rel %>
app/views/kaminari/_next_page.html.erb class属性を追加します。
<span class="next">
-  <%= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, rel: 'next', remote: true %>
+  <%= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, class: "join-item btn", rel: 'next', remote: true %>
</span>

今までの実装で、おおよそこのような状態になっているかと思います。
Image from Gyazo

サイズ調整もできます! 前述のdaisyUIのページネーションのサイトに、サイズ調整用のコンポーネントも用意されています。 お好みでサイズ調整してみてください。

Image from Gyazo

Image from Gyazo

2.5. ページ数の表示制限

2.4までの実装では、ページネーションのapp/views/kaminari/_page.html.erbの表示数を指定していないため、ページ数が多いとページネーションが横に長くなってしまいます。
これは、config/initializers/kaminari_config.rbで下記のような記述を加えることで設定ができます。

config/initializers/kaminari_config.rb
Kaminari.configure do |config|
  config.default_per_page = 5 # 1ページあたりの表示件数
+ config.window = 2 # 現在のページの前後に表示するページ数
end

私の場合は、現在のページ前後に2ページ分表示させたかったため、上記の設定にしました。
ここまでで、レイアウトは下のようになっているかと思います(サイズ調整もしています)。

Image from Gyazo

2.6. 表記をカスタマイズする

現時点では、「Previous」や「Next」といった表記でわかるように、デフォルトでは日本語化されていません。
ここを、日本語で表記されるよう変更してみます。
まず、config/application.rbにてデフォルトの言語設定を日本語に設定します。

config/application.rb
module Myapp
  class Application < Rails::Application
    # Railsアプリケーションのデフォルトの言語設定を日本語に設定
+   config.i18n.default_locale = :ja
  end
end

次に、config/locales/ja.ymlを作成・編集し、「Previous」や「Next」に対応する日本語を設定します。

config/locales/ja.yml
ja:
  views:
    pagination:
      previous: "前へ"
      next: "次へ"

設定ができると下の画像のようになるかと思います。
この後、更にTailwind CSSを利用するなどして、自分好みのレイアウトに調整していただければと思います。

Image from Gyazo

これで終わりになります!お疲れ様でした。

おわりに

以前、bootstrapでページネーションのレイアウト調整をしたことがあったのですが、その時よりも考えることが多く、実装に思ったよりも時間がかかってしまいました。
この記事で同じような実装をお考えの方のお役に立てれば幸いです。

参考

gem 'kaminari'

技術記事

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1