0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Railsのhas_many throughの使い方を簡単にまとめました。

Last updated at Posted at 2021-10-05

Railsチュートリアルの14章で出てきた**「has_many through」**の使い方をわかりやすいように、まとめていきます。
※Railsチュートリアルをやっていないと、いきなりコードを見ても理解できないかもしれないです。
まず、以下のコードを例に説明していきます。

class User < ApplicationRecord
  has_many :active_relationships, class_name:  "Relationship",
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
  has_many :followeds, through: :active_relationships #ここ
#<User id, name, email, created_at, updated_at, password_digest>
end
class Relationship < ApplicationRecord
  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "User"
#<Relationship: id, follower_id, followed_id, created_at, updated_at>
end

throuchの挙動は、
・userモデルのインスタンスにthroughの後に書かれたメソッドを実行する。
・・戻り値のrelationshipインスタンスにhas manyの第一引数を単数系にした、メソッドをインスタンス一つ一つに実行する

↑この説明じゃわからないと思うので、もう少しわかりやすく説明していきます。


まず**「・userモデルのインスタンスにthroughの後に書かれたメソッドを実行する。」**についてです。

has_many :followeds, through: :active_relationships

userモデルに対して「through: :active_relationships」に書かれている「:active_relationships」メソッドを実行します。
↓つまり内部でこんな感じに動きます。

user = User.first #仮に最初のユーザーだったら
relationships  user.active_relationships

active_relationshipsメソッドは
user.id == relationship.follower_idのrelationshipインスタンスの集合を返すので
relationships変数の中には、relationshipインスタンスの集合が入っています。


次に**「・戻り値のrelationshipインスタンスにhas manyの第一引数を単数系にした、メソッドをインスタンス一つ一つに実行する」**の部分です。


has_many :followeds, through: :active_relationships

has_manyの第一引数の:followedsを単数系にするとfollowedになり、
先ほどのrelationship変数に対してfollowedメソッドを実行します。
followedメソッドはRelationshipモデル内のbelongs_toで生成されたメソッドです。

belongs_to :followed, class_name: "User"

↓内部ではこうなっています。

user = User.first#仮に最初のユーザーだったら
relationships  user.active_relationships
relationships.map(&:followed)

この一連の流れを「has_many :followeds, through: :active_relationships」で生成した。followedsメソッドをuserインスタンスに対して呼び出すと実行してくれます。


###第一引数を任意の単語に変更することもできます。
:followedsを :followingに変更します。
ですがこれではfollowed_idと紐ずくuserインスタンスを取得できません。
そのため明示的にsource: :followedとしてfollowed_idと紐ずくuserインスタンスが欲しいとrailsに伝える必要があります。

class User < ApplicationRecord
  has_many :active_relationships, class_name:  "Relationship",
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
  has_many :following, through: :active_relationships, source: :followed

end

##まとめると

user.following

と書くと内部では、

user.active_relationships.map(&:followed)

このような処理が行われています。

※厳密に言うとmapを使うと戻り値は配列で、user.followingを使うと戻り値のクラスは「User::ActiveRecord_Associations_CollectionProxy」になるみたいですが、データの集合が取得できるという意味では近いイメージです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?