Railsでpagyを使ったページネーション

この記事は[高知工科大 Advent Calendar 2018](https://adventar.org/calendars/2959)の第６日目の記事です。
学生っぽい文調で書きます。

# はじめに
こんにちは。Qiitaに投稿しようかなと温めていたネタを、どうせならアドカレに載せちゃおう的な感じで書きます。最初は温めてたんですが放置したら冷めちゃったんで温め直しました。  
Ruby on Railsでページネーションの話になります。
RailsでWebアプリを作るときにコンテンツを５個位に分けてページ分けするヤツを実装したいなって調べてたら、初めてページネーションって名前なの知りました。
Google検索とかAmazonとかで検索するときに２ページ目、３ページ目とかいけるアレです。

# 概要
Ruby on Railsでのページネーションに「pagy」というgemを用いて実装します。
github: https://github.com/ddnexus/pagy  
あと、pagyだと味気ないのでササッとBootstrapで装飾します。
## pagyについて
Railsのページネーションにはkaminariとかwill_pagenateというgemを使うのが一般的？らしいんですがpagyはそれらと比べて"速く"、"省メモリ"、"シンプル"かつ"効率的"というベンチマーク結果が出ているらしいです。
ちなみに私はpagyしか使ったことありません。

## 環境
```
Ruby 2.5.1
Rails 5.2.1
pagy 1.1.0
```

# 実装
実際の導入手順書いていきます。最後にgithubのリンク貼るのでそちらの確認もどうぞ

## Install
```:Gemfile
gem 'pagy'
```
Gemfileにpagyを追加して、bundle installをします。

```:bash
$ bundle install
```
## Config
pagyを使うための設定をします。

- 一度に表示するコンテンツの数
- Bootstrapのrequire

などです。
設定ファイルとして pagy.rb を config/initializers 下に配置します。
設定ファイルは自分で作るか、公式で配布されているテンプレートをダウンロードして使うかの２択です。
[公式テンプレート](https://github.com/ddnexus/pagy/blob/master/lib/config/pagy.rb)
私は一度に５個のコンテンツを表示する設定にしているので次のような感じになってます。

```rb:config/initializers/pagy.rb
# pagy config file
Pagy::VARS[:items] = 5
```

## Controller
pagyを導入したいcontrollerに次の文を記述します。
あ、言い忘れましたが、私のアプリケーションに導入した際の例で説明していきます。

```rb:app/controllers/pages_controller.rb
class PagesController < ApplicationController
  include Pagy::Backend
```

次にモデルを引数に入れてpagyを使います！

```rb:app/controllers/pages_controller.rb
  def posts
    @pagy, @posts = pagy(Post.all)
  end
```

@pagyには、paginationの何か(わかってない)が、@postsにはモデルアクションの結果(Post.all)が格納されます。

## View
viewで画面表示周りをいじります。
まず、helperに次の文を記述します。

```rb:app/helper/pages_helper.rb
module PagesHelper
  include Pagy::Frontend
end
```

次に、viewで個々の表示とpagyの設定をします。

```erb:app/views/pages/show.html.erb
<% @posts.each do |post| %>
  <p><%= post.name %></p>
  <ul>
    <li><%= post.content %></li>
  </ul>
<% end %>
<%== pagy_nav(@pagy) %>
```

@postsに格納されたデータを１個１個、postという変数に格納して、それを表示しています。
下はこんな感じだよっていう画像です。seedは適当に入れてます。

<img width="538" alt="スクリーンショット 2018-12-03 16.07.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/233730/ddb41aad-6b94-4143-10a3-65ff76b7834a.png">

## Bootstrap
一応これで完成ですが味気ないのでBootstrapでちゃちゃっとそれっぽくしたいですね
まず、RailsにBootstrapを適用させます。
[RailsのBootstrap覚え書き](https://qiita.com/white0221/items/ed4f22551ee35ed36607)
この記事から適用させちゃってください。

あとはpagyにbootstrap用の文を追加していきます。

```rb:config/initializers/pagy.rb
require 'pagy/extras/bootstrap'
```

```erb:app/views/pages/show.html.erb
<div class="d-flex justify-content-left mb-2">
  <%== pagy_nav_bootstrap(@pagy) %>
</div>
```

こんな雰囲気になると思います。
<img width="282" alt="スクリーンショット 2018-12-03 16.41.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/233730/943396c9-5695-8a3d-3290-aa8a2a466417.png">

## SearchResult
小見出し思いつかなくてわけのわからない小見出しになってしまいました。反省してます。
@pagyにpaginationの何かが入るってゆってたんですけど、検索結果の件数とかわかります。

```rb:
if @pagy.vars[:count] > 0
  # 検索結果がある
else
  # 検索結果がゼロ
end
```

こんなことをコントローラに書いたりビューの中に書いたりしていろいろできるのではないかと思います。
# 終わりに
画像を全然載せないので分かりづらかったかもしれないです。
自分の実装した範囲でしか説明できてないのでpagyの深い使い方とか、まだまだあるんじゃないかと思います。
個人的にpagyのbootstrap適用が一番手こずりました。たしか。

今回の実装手順をGithubにあげてます。
https://github.com/white0221/pagy
区切りごとにコミットで分けたつもりなのでよければご参考にしてください。

それではRuby on Railsにpagyの適用方法でした。
開発の助けになれば幸いです。

## 参考資料
https://qiita.com/junara/items/eb85559547f87c8cb6b3
https://techracho.bpsinc.jp/hachi8833/2018_06_05/57481