2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Rails]テーブルにページネーションを付ける[初心者向け]

Posted at

以下のようなページネーションを実装する

ページネーション.png

注意

画像に表示されているメールアドレスは実在のものではありません
RailsにBootstrapが適用されていること

参考:Railsアプリで Bootstrap 4 を利用する - Qiita

環境

  • rails:5.1.6
  • ruby:2.6.3p62

初期コード

コントローラ

app/controllers/users_controller.rb
### 以上略 ###
def index
  @users = User.all
end
### 以下略 ###

ビュー

app/views/users/index.html.erb
<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が全て表示されている
初期画面.png
実現したい画面(1ページ目)
20件ずつ表示する
ページネーション_1st.png
実現したい画面(2ページ目)
全21件なので2ページ目は1件のみ
ページネーション_2nd.png

ページネーション機能実装

実装部分

ページネーションを実現するには、kaminariを使う
以下を追記

Gemfile
gem 'kaminari'
gem 'kaminari-bootstrap'

以下でgemをインストール

console
bundle install

コントローラー
per(num):numは何件ごと表示するか(今回は20件ごと)
以下の差分を参考に変更

app/controllers/users_controller.rb
 def index
-  @users = User.all
+  @users = User.page(params[:page]).per(20)
 end

ビュー
paginateを書いたところにページネーションが表示される(今回はテーブルの後ろにする)

app/views/users/index.html.erb
 <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>
画面(一部省略)
ページネーション01.png

ページネーションが実現できているが、見た目がダサいし使いづらい

見た目の変更

以下でkaminariをカスタマイズするファイル作成

console
rails g kaminari:views default

以下が表示されていれば、app/viewskaminariフォルダが生成されている

結果
      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クラスを適用する)

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, class: 'page-link' %>
</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, class: 'page-link' %>
</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 => remote, class: 'page-link' %>
</span>
app/views/kaminari/_page.html.erb
<% 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 %>
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 => remote, class: 'page-link' %>
</span>

ついでに、ページネーションを中央寄せにする

app/assets/stylesheets/application.scss
.pagination {
  justify-content: center;
}

画面(一部省略)
ページネーションpage-link_中央寄せ.png

ページネーション機能完了
NextやLastなどの日本語化方法は省略します

参考

【rails】kaminariを使ってページネーションを作る - Qiita
【Rails】kaminariの使い方をマスターしよう! - Pikawaka
Kaminariの使い方 まとめ - Hatena Blog

おまけ

追加用件として以下が考えられる

  • 1ページあたりの表示件数を20件と決め打ちしたが、利用者が表示件数を切り替えられるようにしたい
  • 全部で何件あって、そのうち何件ページネーションで表示されているのか知りたい
イメージ(一部省略)
完成イメージ.png

利用者が表示件数を切り替えられる機能

コントローラー

app/controllers/users_controller.rb
 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

ビュー

app/views/users/index.html.erb
 <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| %>
 ### 以下略 ###
表示件数切り替え画面(一部省略)
今回はテーブルの上に表示した
場所はお好みで

表示件数切り替え機能.png

全件数と表示件数表示

ビュー

app/views/users/index.html.erb
 <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件のみなので正しく表示されている(左上)

全件と件数表示画面.png

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?