62
61

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 5 years have passed since last update.

[Rails]will_paginateで表示件数を選択できるページネーションを実装する

Last updated at Posted at 2018-07-17

Railsでデータ表を表示する際、行数(データ数)が多い場合には当然ページが無駄に長くなってしまうため、ページ分割を行った方が良い。
ここではページネーションが簡単に実装できるGem「will_paginate」を紹介して、+αとしてドロップボタンによる表示件数選択も実装する。

ページネーション

ページ割りのこと。一番馴染み深い例で言えば、Google検索のコレ。
スクリーンショット 2018-07-17 23.56.42.png
ページにデータ表を作る際にn行ずつ表示させることで、よりスッキリしたデザインにできる。

will_paginateによる実装

book_list.html.erbに、こんな感じの表を作成したとする。

スクリーンショット 2018-07-18 0.11.25.png

12件一気に表示すると縦に長くなってしまうため、まずは5件ずつ表示するようにページネーションを実装する。

※参考
http://blog.otsukasatoshi.com/entry/2017/07/10/120000

まずはGemfileにwill_paginateを追加する

gem 'will_paginate'
gem 'bootstrap-will_paginate'

will_paginateだけでもページネーションは実装できるが、見た目が圧倒的に良くなるのでbootstrap-will_paginateも追加する事を推奨する。

次に、Controllerを以下のように修正

book_controller.rb
def book_list
   @books = Book.paginate(page: params[:page], per_page: 5)
end

will_paginateが導入されている時点で、各Modelにpaginateメソッドが追加される。
表示するデータがBookの全データだった場合は、.allが.paginateに置き換わるだけ。
**page:**は参照しているページ番号の事で、これは自動的に設定される値なのでそのままでOK。
**per_page:**は1ページに表示する件数。今回は5件ごとに表示するので5。

最後にViewに以下の2行を追加。

book_list.html.erb
<tbody class="text-center">
 <%= will_paginate @books, :previous_label => ' &lt 前へ', :next_label => '次へ &gt' %> # この行と
  <% @books.each do |book| %>
   <tr>
    <td><%= book.id %></td>
    <td><%= book.title %></td>
     [...省略...]
   </tr>
  <% end %>
</tbody>
<%= will_paginate @books, :previous_label => ' &lt 前へ', :next_label => '次へ &gt' %> # この行を追記

これだけでページネーションの実装が完了する。will_paginateすごい。
Viewで追加する行は

<%= will_paginate @books %>

だけで十分であるが、defaultだと「前へ」「後ろへ」の表記が英語になってしまうため、上のコードでは少しいじってある。

実際に動かしてみたモノがこちら。
スクリーンショット 2018-07-18 0.30.31.png

Viewで挿入した位置に、ちゃんとボタンが追加されている。bootstrap-will_paginateのおかげで見た目も悪くない。

表示件数選択機能

上の例では5件ずつ表示したが、表示件数も弄れるようにした方が快適なので、ドロップダウンから設定できるようにする。
will_paginateのREADMEを見たところ、そういうドロップダウンボタンが用意されてる訳ではないようなので、自分で作成する。

ここでは"/book_list/:件数"に飛ばして、paramsからper_pageを設定することとする。
ただし、:pageはpaginateで予約されているため、パラメータ名は別の単語を使う(ここでは**:per**とする)

route.rb
get "book_list/:per" => "book#book_list_page"
get "book_list" => "book#book_list"
book_controller.rb
def book_list
   @page = 5
   @books = Book.paginate(page: params[:page], per_page: @page)
end

def book_list_page
   @page = params[:per]
   @books = Book.paginate(page: params[:page], per_page: @page)
   render("book_list")
end
```

```erb:book_list.html.erb
<div class="dropdown">
 <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
  <%= @page %>
  <span class="caret"></span>
 </button>
 <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
  <li><%= link_to("3", "/book_list/3") %></li>
  <li><%= link_to("5", "/book_list/5") %></li>
  <li><%= link_to("10", "/book_list/10") %></li>
  <li><%= link_to("20", "/book_list/20") %></li>
 </ul>
 <label>件ずつ表示する</label>
</div>

<thead class="text-center">
[...省略...]
<tbody class="text-center">
 <%= will_paginate @books, :previous_label => ' &lt 前へ', :next_label => '次へ &gt' %>
  <% @books.each do |book| %>
   <tr>
    <td><%= book.id %></td>
    <td><%= book.title %></td>
     [...省略...]
   </tr>
  <% end %>
</tbody>
<%= will_paginate @books, :previous_label => ' &lt 前へ', :next_label => '次へ &gt' %>
[以下略]
```

これを実装した結果がこちら。
<img width="1197" alt="スクリーンショット 2018-07-18 0.52.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/197878/ad508d15-28e1-d32d-4980-29c911779538.png">
左上のドロップダウンから表示件数が選択でき、表示件数を変えるたびにページ数も変化する。

# まとめ
will_paginateで簡単にページネーションが実装できた。
表示件数を設定するボタンも実装することができた。
62
61
1

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
62
61

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?