はじめに
こんにちは、ゆうき(@yuki31100725)と申します。
現在、プログラミングスクールに通ってRuby on Railsを学習しております。
私はプログラミング学習中で、初学者です。
内容に誤りのある場合がございます。
もし間違いがあればご指摘いただけますと幸いです。
記事の概要
gem 'kaminari'を導入してページネーションを実装した際、導入済みだったTailwind CSS (+ daisyUI)を用いてレイアウト調整を試みました。
本記事では、実装例とともにレイアウト調整の手順についてご紹介できればと思います。
記事のゴール
gem 'kaminari'でページネーション実装後、Tailwind CSS (+ daisyUI)を用いて下記のようなレイアウトにすることを目標としています。
背景
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)未導入であっても、下記のような流れでレイアウト調整できるため、途中まではご参考になるかと思います。
- gem 'kaminari' におけるビューのカスタムテンプレートを導入
- ページネーションの見た目をCSSで整える
ページネーションとgem 'kaminari'について
ページネーションについて
ページネーションとは、大量のデータを複数のページに分割して表示する技術を指します。
この技術を使用することで、ページの読み込み時間を短縮することが可能になります。
下の画像はGoogleの検索結果画面でよく見るページネーションのデザインになります。
gem 'kaminari'について
gem 'kaminari'はページネーションを簡単に実装するためのgemです。
実装手順
手順概要
-
ページネーションの導入
1.1. kaminariをGemfileに追加する
1.2. 設定ファイルを生成し、初期設定を変更する
1.3. コントローラーの記述を修正する
1.4. ビューの設定を記述する -
ページネーションのカスタマイズ
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にしました。
Kaminari.configure do |config|
config.default_per_page = 5 # 1ページあたりの表示件数
end
1.3. コントローラーの記述を修正する
ページネーションを利用したいデータの取得を担っているコントローラーの記述を修正します。
私の場合は、施設の情報一覧を取得するspotsコントローラーのindexアクションに適用してみました。
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ヘルパーを用いて下記のように記述します。
<%= paginate @spots %>
これにより、下の画像のようなページネーションが作成されるかと思います(若干異なる可能性もあります)。
ここまでで、最低限のページネーションの機能ができました。
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を新たに導入することで、カスタムテンプレートを使用せず簡単にレイアウト調整ができるということで、その場合の実装例が書かれた資料もこちらに記載しておきます。
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におけるページネーションのコンポーネントはこちらから確認できます。
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>
今までの実装で、おおよそこのような状態になっているかと思います。
2.5. ページ数の表示制限
2.4までの実装では、ページネーションのapp/views/kaminari/_page.html.erb
の表示数を指定していないため、ページ数が多いとページネーションが横に長くなってしまいます。
これは、config/initializers/kaminari_config.rb
で下記のような記述を加えることで設定ができます。
Kaminari.configure do |config|
config.default_per_page = 5 # 1ページあたりの表示件数
+ config.window = 2 # 現在のページの前後に表示するページ数
end
私の場合は、現在のページ前後に2ページ分表示させたかったため、上記の設定にしました。
ここまでで、レイアウトは下のようになっているかと思います(サイズ調整もしています)。
2.6. 表記をカスタマイズする
現時点では、「Previous」や「Next」といった表記でわかるように、デフォルトでは日本語化されていません。
ここを、日本語で表記されるよう変更してみます。
まず、config/application.rb
にてデフォルトの言語設定を日本語に設定します。
module Myapp
class Application < Rails::Application
# Railsアプリケーションのデフォルトの言語設定を日本語に設定
+ config.i18n.default_locale = :ja
end
end
次に、config/locales/ja.yml
を作成・編集し、「Previous」や「Next」に対応する日本語を設定します。
ja:
views:
pagination:
previous: "前へ"
next: "次へ"
設定ができると下の画像のようになるかと思います。
この後、更にTailwind CSSを利用するなどして、自分好みのレイアウトに調整していただければと思います。
これで終わりになります!お疲れ様でした。
おわりに
以前、bootstrapでページネーションのレイアウト調整をしたことがあったのですが、その時よりも考えることが多く、実装に思ったよりも時間がかかってしまいました。
この記事で同じような実装をお考えの方のお役に立てれば幸いです。
参考
gem 'kaminari'
技術記事