以下のようなページネーションを実装する
注意
画像に表示されているメールアドレスは実在のものではありません
RailsにBootstrapが適用されていること
環境
- rails:5.1.6
- ruby:2.6.3p62
初期コード
コントローラ
### 以上略 ###
def index
@users = User.all
end
### 以下略 ###
ビュー
<div class="mt-2 mb-2 mr-5 ml-5 pr-5 pl-5">
<table class="table table-sm table-hover">
<thead class="thead-dark">
<tr>
<th>Name</th>
<th>Email</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.email %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
初期画面と実現したい画面
初期画面 |
---|
Userが全て表示されている |
実現したい画面(1ページ目) |
---|
20件ずつ表示する |
実現したい画面(2ページ目) |
---|
全21件なので2ページ目は1件のみ |
ページネーション機能実装
実装部分
ページネーションを実現するには、kaminariを使う
以下を追記
gem 'kaminari'
gem 'kaminari-bootstrap'
以下でgemをインストール
bundle install
コントローラー
per(num)
:numは何件ごと表示するか(今回は20件ごと)
以下の差分を参考に変更
def index
- @users = User.all
+ @users = User.page(params[:page]).per(20)
end
ビュー
paginate
を書いたところにページネーションが表示される(今回はテーブルの後ろにする)
<div class="mt-2 mb-2 mr-5 ml-5 pr-5 pl-5">
<table class="table table-sm table-hover">
<thead class="thead-dark">
<tr>
<th>Name</th>
<th>Email</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.email %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
+ <%= paginate @users %>
</div>
画面(一部省略) |
---|
ページネーションが実現できているが、見た目がダサいし使いづらい
見た目の変更
以下でkaminariをカスタマイズするファイル作成
rails g kaminari:views default
以下が表示されていれば、app/views
にkaminari
フォルダが生成されている
create app/views/kaminari/_paginator.html.erb
create app/views/kaminari/_prev_page.html.erb
create app/views/kaminari/_page.html.erb
create app/views/kaminari/_last_page.html.erb
create app/views/kaminari/_gap.html.erb
create app/views/kaminari/_first_page.html.erb
create app/views/kaminari/_next_page.html.erb
app/views/kaminari
に生成されたファイルを編集する(主にpage-linkクラスを適用する)
<span class="first">
<%= link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, :remote => remote, class: 'page-link' %>
</span>
<span class="last">
<%= link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, :remote => remote, class: 'page-link' %>
</span>
<span class="next">
<%= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, :rel => 'next', :remote => remote, class: 'page-link' %>
</span>
<% if page.current? %>
<span class="page-item disabled">
<%= link_to page, url, {class: 'page-link'} %>
</span>
<% else %>
<span class="page-item">
<%= link_to_unless page.current?, page, url, {:remote => remote, class: 'page-link', :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} %>
</span>
<% end %>
<span class="prev">
<%= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, :rel => 'prev', :remote => remote, class: 'page-link' %>
</span>
ついでに、ページネーションを中央寄せにする
.pagination {
justify-content: center;
}
画面(一部省略) |
---|
ページネーション機能完了
NextやLastなどの日本語化方法は省略します
参考
【rails】kaminariを使ってページネーションを作る - Qiita
【Rails】kaminariの使い方をマスターしよう! - Pikawaka
Kaminariの使い方 まとめ - Hatena Blog
おまけ
追加用件として以下が考えられる
- 1ページあたりの表示件数を20件と決め打ちしたが、利用者が表示件数を切り替えられるようにしたい
- 全部で何件あって、そのうち何件ページネーションで表示されているのか知りたい
イメージ(一部省略) |
---|
利用者が表示件数を切り替えられる機能
コントローラー
def index
- @users = User.page(params[:page]).per(20)
+ @users = User.page(params[:page]).per(per_page)
end
### 以下一部省略 ###
private
+ def per_page
+ # 今回は5, 10, 20, 50, 100件で利用者が切り替えられるようにする(デフォルトは20)
+ %W[5 10 20 50 100].include?(params[:per]) ? params[:per] : 20
+ end
ビュー
<div class="mt-2 mb-2 mr-5 ml-5 pr-5 pl-5">
+ <div class="float-right">
+ 表示件数:
+ <% [5, 10, 20, 50, 100].each do |per| %>
+ <% unless @users.limit_value == per %>
+ <%= link_to per, users_path(per: per), {class: 'mr-2'} %>
+ <% else %>
+ <a class="mr-2"><%= per %></a>
+ <% end %>
+ <% end %>
+ </div>
<table class="table table-sm table-hover">
<thead class="thead-dark">
<tr>
<th>Name</th>
<th>Email</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
### 以下略 ###
表示件数切り替え画面(一部省略) |
---|
今回はテーブルの上に表示した |
場所はお好みで |
全件数と表示件数表示
ビュー
<div class="mt-2 mb-2 mr-5 ml-5 pr-5 pl-5">
+ <div class="float-left">
+ <%= "#{@users.count}件 / #{@users.total_count}件" %>
+ </div>
<div class="float-right">
表示件数:
<% [5, 10, 20, 50, 100].each do |per| %>
<% unless @users.limit_value == per %>
<%= link_to per, users_path(per: per), {class: 'mr-2'} %>
<% else %>
<a class="mr-2"><%= per %></a>
<% end %>
<% end %>
</div>
### 以下略 ###
全件数と表示件数表示画面 |
---|
1ページあたりの表示件数を20件としているが、最後のページは1件のみなので正しく表示されている(左上) |