はじめに
フォロー機能を実装したらthroughこの文言が出てきたので色々調べてみた。
今回は前に実装していた、いいねした投稿一覧をthroughを使ってスッキリさせていこうと思う。
割と丁寧に解説したと思うので、少しでも参考になれば幸いです。
使用する環境
- MacOS(Intel)
- Rails 6.0.3
- Ruby 2.6.3
- yarn 1.22.17
- Homebrew 3.5.0
まず結論から
まずUserモデルの編集
Before
has_many :posts, dependent: :destroy
has_many :favorites, dependent: :destroy
After
has_many :posts, dependent: :destroy
has_many :favorites, dependent: :destroy
has_many :likes, through: :favorites, source: :post # 追加
Before
def favorite_list
favorites = Favorite.where(user_id: current_user.id).order(updated_at: :desc).pluck(:post_id)
@post_favorites = Post.find(favorites)
end
After
def favorite_list
@post_favorites = current_user.likes
end
コードの解説
こちらのコードの解説をしていきます。
目的は:ログインしてるユーザーがいいねした投稿一覧が欲しい
まず、ログインしてるユーザーをAさんとして、
Aさんのいいね一覧を取得しようとしたら、current_user.favoritesで取得できると思います。
ただ、これだと私のDB設計だと投稿一覧を取得はできません。
私の場合は、下記のような形になります。
これは、いいねした投稿のIDとその投稿を誰がいいねしたかのuser_id(今回例だとログインしてるユーザー)になります。
=> [#<Favorite:0x0000000107926a50 id: 362, user_id: 13, post_id: 38, created_at: Mon, 08 Aug 2022 05:13:56.783515000 UTC +00:00, updated_at: Mon, 08 Aug 2022 05:13:56.783515000 UTC +00:00>,
#<Favorite:0x000000010796cf28 id: 380, user_id: 13, post_id: 37, created_at: Thu, 11 Aug 2022 01:29:59.467057000 UTC +00:00, updated_at: Thu, 11 Aug 2022 01:29:59.467057000 UTC +00:00>,
#<Favorite:0x000000010796cdc0 id: 426, user_id: 13, post_id: 39, created_at: Thu, 11 Aug 2022 15:47:55.832642000 UTC +00:00, updated_at: Thu, 11 Aug 2022 15:47:55.832642000 UTC +00:00>]
本当は、下記のような形で書きたいのですけど、エラー出ます。
でも、throughを使えば下記のような形でスッキリ書くことができるのです。
current_user.favorites.posts
再度userモデルに書いたのをみていきましょう。
has_many :likes, through: :favorites, source: :post
これは、user→favorites→postsというアソシエーションに、likesという別名をつけています。
likesだけだとlikesテーブルを参照しに行ってしまうため、source: :postをつけてpostsテーブルを参照するようにしています。
この書き方は初めてみると少しわかりにくいかもしれませんが、要は、あるUserがいいねした投稿を取得できると考えると少しはわかりやすいかもしれません。(わかりにくかったらすみません)
これを追記したら、あとは簡単です。
先ほど追記したコードでUserがいいねした投稿一覧をlikesで取れるようになってるので好きなアクションの中で、下記のようにすれば取得できます(勿論ログインしてるユーザー以外のも取れます。)
current_user.likes
ちなみに前までは下記のように書いてたのでだいぶスッキリしましたね!
favorites = Favorite.where(user_id: current_user.id).pluck(:post_id)
@post_favorites = Post.find(favorites)
おまけ(外部のテーブルを参照)
いいねした投稿を降順(新しい順)に並べる方法
@post_favorites = current_user.likes.order("favorites.created_at DESC")
最後に
上手く説明できなかったところもあるかもしれませんが、少しでもお役になったら幸いです
参考にさせていただいた記事:https://qiita.com/tanutanu/items/2a27f1e503c4cbf30928