【Rails】グループ化した際のページネーション

# はじめに
レコードの一覧をグループ化して表示する際のページネーションについて、少し躓いたのでまとめます。
ページネーションはkaminariを使用しています。

# 普段のページネーション
例えば、全てのユーザーを取得して１０件ずつ一覧に表示するようなページネーションは以下のようになります。

```app/controllers/users_controller.rb
def index
  page = params[:page] || 1
  @users = User.all.page(page).per(10)
end
```

```app/views/users/index.html.erb
<table>
  <thead>
    <tr>
      <th>ユーザー情報</th>
    </tr>
  </thead>

  <tbody>
  <% @users.each do |user| %>
    <tr>
      <td>id：<%= user.id %></td>
      <td>name：<%= user.name %></td>
    </tr>
  </tbody>
  <% end %>
</table>
<div class="m_t_30">
  <ul><%= paginate(@users) %></ul>
</div> 
```

また、kaminariでは配列に対してもページネーションをさせることができます。

```app/controllers/users_controller.rb
  def index
    page = params[:page] || 1
    array = []
    users = User.all
    users.each do |user|
      array.push({
        id: user.id,
        name: user.name
      })
    end
    @paginated_array = Kaminari.paginate_array(array).page(params[:page]).per(10)
  end
```

```app/views/users/index.html.erb
<table>
  <thead>
    <tr>
      <th>ユーザー情報</th>
    </tr>
  </thead>

  <tbody>
  <% @paginated_array.each do |item| %>
    <tr>
      <td>id：<%= item[:id] %></td>
      <td>name：<%= item[:name] %></td>
    </tr>
  </tbody>
  <% end %>
</table>
<div class="m_t_30">
  <ul><%= paginate(@paginated_array) %></ul>
</div> 
```

# つまずいた場面
レコードをグループ化して表示させたい場面でのページネーションをどう実装するかで迷いました。

##  例

例えば以下のように、ユーザーを一覧に表示する際に、各ユーザーの持つcountryカラムの値ごとにグループ化して一覧を表示させたい場面があります。

さらにこの画面の中で**ユーザーに対してページネーションをするための実装を想定します。**

<img width="328" alt="スクリーンショット 2020-07-16 0.41.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576866/71d9e841-50a8-c82b-48c3-f1a8ef460156.png">

```app/controllers/users_controller.rb
def index
  # 全てのユーザーを取得し、countryカラムの文字コード順に並べ替える
  users = User.all.order(country: "DESC").order(id: "ASC")
  @users_hash = users.gruop_by {|user| user.country}
end

```

```app/views/users/index.html.erb
<table>
  <thead>
    <tr>
      <th>国別一覧</th>
    </tr>
  </thead>

  <tbody>
    <% @users_hash.keys.each do |country| %>
      <% users = @users_hash[country] %>
        <tr>
          <th><%= country %>グループ</th>
        </tr>
        <% users.each do |user| %>
        <tr>
          <td><%= user.name %></td>
        </tr>
      <% end %>
    <% end %>
  </tbody>
</table>

```
---
グループ化するためにはgroup_byを使用します。
gruop_byを使用すると、
> ブロックを評価した結果をキー、対応する要素の配列を値とするハッシュを返すことができます。

[railsリファレンスマニュアル](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/group_by.html)

先ほど配列に対してページネーションをした際には、配列の中に各ユーザーごとのデータが格納されたハッシュを入れていました。
なので、`users.length`と`Kaminari.paginate_array(array).length`の結果が一致します。*（1ページあたりの項目数はデフォルトだと25なので、users.length < 25の場合）*

しかし、今回の場合ハッシュのkey,valueを配列の値としてpaginate_arrayに入れると`[{key1, [value1, value2]},{key2,[value3, value4, value5]}...]`のようになり、ハッシュのkeyと同様の数（配列の要素数）に対してページネーションがされることになります。

つまり、

```pp/controllers/users_controller.rb
def index
~~
略
array = [{key1, [value1, value2]},{key2,[value3, value4, value5]}...]
@paginated_array = Kaminari.paginate_array(array).page(params[:page]).per(10)
```
とすると、**key**が10項目以上にならなければページネーションされないことになります。
今回のケースでは**value**が10項目以上の場合にページネーションをさせたいので、欲しい出力は得られなません。

# 解決策
以下のように実装することで解決できました。

```app/controllers/users_controller.rb
 def index
    page = params[:page] || 1
    @users = User.all.order(country: "DESC").order(id: "ASC").page(page).per(15)
    @users_hash = @users.group_by {|user| user.country}
  end
```

```app/views/users/index.html.erb
<table>
  <thead>
    <tr>
      <th>国別一覧</th>
    </tr>
  </thead>

  <tbody>
    <% @users_hash.keys.each do |country| %>
      <% users = @users_hash[country] %>
        <tr>
          <th><%= country %>グループ</th>
        </tr>
        <% users.each do |user| %>
        <tr>
          <td><%= user.name %></td>
        </tr>
      <% end %>
    <% end %>
  </tbody>
</table>

<div class="m_t_30">
  <ul><%= paginate(@users) %></ul>
</div>
```

上記の出力は次のようになり、目標としていた出力が得られました！

**１ページ目**
<img width="566" alt="スクリーンショット 2020-07-16 0.26.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576866/93ff1317-be9a-743c-cbd8-1810085c5aea.png">

**2ページ目**
<img width="679" alt="スクリーンショット 2020-07-16 0.26.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576866/92ea26c5-4d06-ed80-26b6-dc347fdad0ea.png">

# 参考
- [kaminari](https://github.com/kaminari/kaminari)
- [Rubyリファレンスマニュアル](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/group_by.html)
- [【rails】kaminariを使ってページネーションを作る](https://qiita.com/you8/items/df68aaee3010e282d1ae)
- [kaminari を使って配列に対してのページャーを作成する](https://blog.konboi.com/post/2013/03/31/224939/)