Railsでデータ表を表示する際、行数(データ数)が多い場合には当然ページが無駄に長くなってしまうため、ページ分割を行った方が良い。
ここではページネーションが簡単に実装できるGem「will_paginate」を紹介して、+αとしてドロップボタンによる表示件数選択も実装する。
ページネーション
ページ割りのこと。一番馴染み深い例で言えば、Google検索のコレ。
ページにデータ表を作る際にn行ずつ表示させることで、よりスッキリしたデザインにできる。
will_paginateによる実装
book_list.html.erbに、こんな感じの表を作成したとする。
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を以下のように修正
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行を追加。
<tbody class="text-center">
<%= will_paginate @books, :previous_label => ' < 前へ', :next_label => '次へ >' %> # この行と
<% @books.each do |book| %>
<tr>
<td><%= book.id %></td>
<td><%= book.title %></td>
[...省略...]
</tr>
<% end %>
</tbody>
<%= will_paginate @books, :previous_label => ' < 前へ', :next_label => '次へ >' %> # この行を追記
これだけでページネーションの実装が完了する。will_paginateすごい。
Viewで追加する行は
<%= will_paginate @books %>
だけで十分であるが、defaultだと「前へ」「後ろへ」の表記が英語になってしまうため、上のコードでは少しいじってある。
Viewで挿入した位置に、ちゃんとボタンが追加されている。bootstrap-will_paginateのおかげで見た目も悪くない。
表示件数選択機能
上の例では5件ずつ表示したが、表示件数も弄れるようにした方が快適なので、ドロップダウンから設定できるようにする。
will_paginateのREADMEを見たところ、そういうドロップダウンボタンが用意されてる訳ではないようなので、自分で作成する。
ここでは"/book_list/:件数"に飛ばして、paramsからper_pageを設定することとする。
ただし、:pageはpaginateで予約されているため、パラメータ名は別の単語を使う(ここでは**:per**とする)
get "book_list/:per" => "book#book_list_page"
get "book_list" => "book#book_list"
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 => ' < 前へ', :next_label => '次へ >' %>
<% @books.each do |book| %>
<tr>
<td><%= book.id %></td>
<td><%= book.title %></td>
[...省略...]
</tr>
<% end %>
</tbody>
<%= will_paginate @books, :previous_label => ' < 前へ', :next_label => '次へ >' %>
[以下略]
```
これを実装した結果がこちら。
<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で簡単にページネーションが実装できた。
表示件数を設定するボタンも実装することができた。