[Rails]Kaminariを使用したページネーション機能でのエラーについて
Railsでページネーション機能を簡単に実装できる便利なgemであるKaminariをいつも通り使おうと思ったらエラーになったので是非どなたかの参考になれば。
前提
- 会員機能(devise)実装済み。
- 投稿機能(post)実装済み。
- Bootstrapを使用。
- いいね機能(今回はfavorite)を実装済み。
行いたいこと
- 今までいいねをした投稿をプロフィールにあるリンクから一覧表示させたもののページネーション。
gemの導入
まずはじめにgemの導入から行います。
特に何もなければ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)に基づいたいいねの一覧を実装していきます。
scope module: :public do
...
resources :members, only: [:index, :show] do
collection do
get 'favorite'
end
end
...
end
resources
の中にcollection
で囲むと/:id
のつかないルーティングをRailsさんが生成してくれます。ちなみにcollection
とmember
があり、後者は逆に/:id
をつけてくれます。
※詳しくはこちらの記事がとても参考になります。↓
※会員(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
コマンドをターミナルに入力してルーティングを確認できたらこちらは完了です。
コントローラーへの記述
次にコントローラーの記述をしていきます。
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
処理としては、まずFavorite
にwhereメソッド
を使いfavoriteテーブルの中のメンバーIDが現在のメンバーIDと一致するレコードを探します。
次にpluckメソッド
を使い特定の値(post_id)だけを絞り込み、配列として取得します。
今回の場合は、現在のメンバーIDと一致するいいねを探し、そのいいねが持っている投稿ID(post_id)を配列として取得しています。
二行目では、@favorite_posts
に先程取得した投稿ID(post_id)と一致する投稿(post)を取得し、代入します。こちらには配列として情報が入っています。
最後に、find
で取得した値はページ付け可能配列ではない配列(array)として返ってくるので、通常の記述とは異なるKaminari
のpageメソッド
であるKaminari.paginate_array(引数)
の記述が必要です。これにより配列でもページネーションを実現することができます。
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
でないために起こるエラーです。
ここまでで機能部分の作成は完了しました。
ビューファイルを編集する
最後にビューファイルにページネーションのバーを追加して完了です。
<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を当ててあげるだけです。
/* 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ファイル↓
ja:
views:
pagination:
first: "«"
last: "»"
previous: "‹"
next: "›"
truncate: "..."
«
は「<<」、 »
は「>>」、 ‹
は「<」、 ›
は「>」を表しています。
truncate:
はページ数が多くなってしまった時の省略表記です。
こちらで実装は以上となります。
最後に
同じ配列でもページ付け可能配列のように種類があるとは知らずそのままいつも通りにpage
を当てたらエラーが起きてしまったので記事として残しておきました。
どなたかの参考になれば幸いです。
なにか間違い(誤字脱字、技術面等)があればご指摘ください。
最後まで見てくださりありがとうございました。一緒に勉強がんばりましょう!
Discussion