🙌

[Rails]Kaminariを使用したページネーション機能でのエラーについて

2023/07/24に公開

Railsでページネーション機能を簡単に実装できる便利なgemであるKaminariをいつも通り使おうと思ったらエラーになったので是非どなたかの参考になれば。


前提

  • 会員機能(devise)実装済み。
  • 投稿機能(post)実装済み。
  • Bootstrapを使用。
  • いいね機能(今回はfavorite)を実装済み。

行いたいこと

  • 今までいいねをした投稿をプロフィールにあるリンクから一覧表示させたもののページネーション。

gemの導入

まずはじめにgemの導入から行います。
特に何もなければGemfileの一番下に書くので良いと思います。

Gemfile
...
 gem 'kaminari','~> 1.2.1'
 gem 'bootstrap5-kaminari-views', '~> 0.0.1'

今回Bootstrapを導入済みなので簡単にそれなりのデザインになるbootstrap5-kaminari-viewsもこのタイミングで一緒に導入してしまいます。
それではbundle installを行います。

  Bundle complete! 28 Gemfile dependencies, 100 gems now installed.
 Gems in the group 'production' were not installed.
 Use `bundle info [gemname]` to see where a bundled gem is installed.
 ec2-user:~/environment/"アプリケーション名" (develop) $ 

このように表示されれば完了です。

ルーティングの設定

次はルーティングです。
今回は会員(member)に基づいたいいねの一覧を実装していきます。

config.routes.rb
 scope module: :public do
  ...
  resources :members, only: [:index, :show] do
   collection do
    get   'favorite'
   end
  end
  ...
 end

resourcesの中にcollectionで囲むと/:idのつかないルーティングをRailsさんが生成してくれます。ちなみにcollectionmemberがあり、後者は逆に/:idをつけてくれます。
※詳しくはこちらの記事がとても参考になります。↓
https://pikawaka.com/rails/resources#memberの使い方
※会員(member)に関連付けてもでもいいね(favorite)に関連付けてもどちらでも良いと思います。
ただ、記事を書きながら大概余っているいいね(favorite)のindexあたりを使った方がよかったなと感じています。。

  members GET            /members(.:format)           public/members#index
  member GET             /members/:id(.:format)       public/members#show
  favorite_members GET   /members/favorite(.:format)  public/members#favorite

ではrails routeコマンドをターミナルに入力してルーティングを確認できたらこちらは完了です。

コントローラーへの記述

次にコントローラーの記述をしていきます。

app/public/members_controller.rb
 class Public::MembersController < ApplicationController
  ...
  def favorite
   favorites = Favorite.where(member_id: current_member.id).pluck(:post_id)
   @favorite_posts = Post.find(favorites)        
   @favorite_posts = Kaminari.paginate_array(@favorite_posts).page(params[:page]).per(5)
  end
  end
  ...
 end

処理としては、まずFavoritewhereメソッドを使いfavoriteテーブルの中のメンバーIDが現在のメンバーIDと一致するレコードを探します。
次にpluckメソッドを使い特定の値(post_id)だけを絞り込み、配列として取得します。
今回の場合は、現在のメンバーIDと一致するいいねを探し、そのいいねが持っている投稿ID(post_id)を配列として取得しています。
二行目では、@favorite_postsに先程取得した投稿ID(post_id)と一致する投稿(post)を取得し、代入します。こちらには配列として情報が入っています。
最後に、findで取得した値はページ付け可能配列ではない配列(array)として返ってくるので、通常の記述とは異なるKaminaripageメソッドであるKaminari.paginate_array(引数)の記述が必要です。これにより配列でもページネーションを実現することができます。

app/public/members_controller.rb
 class Public::MembersController < ApplicationController
  ...
  def favorite
   favorites = Favorite.where(member_id: current_member.id).pluck(:post_id)
   @favorite_posts = Post.find(favorites).page(params[:page]).per(5)
  end
  ...
 end

こちらのコードにより出ているエラー内容

というふうにNoMethodErrorが出ています。
こちらはページ付け可能配列Arrayでないために起こるエラーです。

ここまでで機能部分の作成は完了しました。

ビューファイルを編集する

最後にビューファイルにページネーションのバーを追加して完了です。

app/views/public/members/favorite.html.erb
 <div class="container">
 ...
  <div class="row mb-5">
   <div class="mx-auto mb-5">
    <%= paginate @favorite_posts, theme: 'bootstrap-5' %>
   </div>
  </div>
 </div>

最初にbootstrap5-kaminari-viewsを導入しているので簡単にそれっぽいページネーションのバーが作れます。記述は上記にもあるようにtheme: 'bootstrap-5'だけです。
ただ、デフォルトでは青いバーが表示されるので、色を好みの色に変えるのがおすすめです。
こちらも簡単で、cssを当ててあげるだけです。

app/javascript/stylesheets/layouts.scss
 /* pagenation layouts */
$pagenation_color: rgb(169,169,169);

 .page-item.active .page-link {
   background-color: $pagenation_color;
   border-color: $pagenation_color;
 }
 .a page-link {
   color: $pagenation_color;
 }
 .page-item a:hover {
   color: $pagenation_color;
 }
 .page-item a {
   color: $pagenation_color;
 }

これで好みの色に変えることができます。
$pagenation_colorと定義してあげることで使い回しが効き、修正時にとても効率的になります。
変数名はわかりやすくしておきました。

cssの当て方によってデザインをもっと変えることもできます。
また、デフォルトでは大なり小なりではなく英語表記になっているのでこちらもお好みで日本語表記に変えることもできます。jaファイル↓

config/locals/ja.yml
 ja:
   views:
     pagination:
       first:      "&laquo;"
       last:       "&raquo;"
       previous:   "&lsaquo;"
       next:       "&rsaquo;"
       truncate:   "..."

&laquo; は「<<」、 &raquo;は「>>」、 &lsaquo;は「<」、 &rsaquo;は「>」を表しています。
truncate:はページ数が多くなってしまった時の省略表記です。

こちらで実装は以上となります。

最後に

同じ配列でもページ付け可能配列のように種類があるとは知らずそのままいつも通りにpageを当てたらエラーが起きてしまったので記事として残しておきました。
どなたかの参考になれば幸いです。

なにか間違い(誤字脱字、技術面等)があればご指摘ください。
最後まで見てくださりありがとうございました。一緒に勉強がんばりましょう!

Discussion