まずhas_many throughを使うにあたっての注意事項
普通has_many throughは3つのモデルを必要とするが、このfollow機能に関しては、1つのモデルを別の見方をして3つのモデルとみなすところがややこしい。
それをふまえて作成のおおまかな流れを書いていく。
前提として、フォローすることを考えた時の能動的関係を表す時、relationshipモデルのことをactive_relationshipモデルとし、フォローされることを考えた時の受動的関係を表す時relationshipモデルのことをpassive_relationshipモデルとする。
生成する中間テーブルは1つ(relationshipsテーブル)だが、
場合によってこいつもまた2つの名前を使い分けるからややこしいから注意。
このテーブルの中にはfollower_idとfollowing_idのカラムがある。もちろんその他勝手に生成されるカラムもあるけどここでは省く。
今回の場合だと、
userモデルが2つあり(本当は一つだけど仮想的に2
つと考えている)、その間にrelationshipモデルが挟まっていて、フォローしている人とされている人の関係を仲介している状態を常に想像してもらうと良い。
非常に考えずらい。
そして、その2つのユーザーモデルはどちらか一方がfollowerならもう一方はfolloingとして考えるとすっきりする。
1.まずフォローすることのみを考えたモデルの関連を考える。(1対多)
これは簡単に言えば、
active_relationship.~
メソッドを作成することを考える。
たとえば
active_relationship.following
で、あるユーザーA*が*フォローしているユーザーを返すメソッドや、
user.active_relationships.build(following_id: user.id)
これで「フォローする」メソッドなどが作成できる。
もちろんその前に
relationshipモデルに
belongs_toを追加してからじゃないと使えないから注意。
まぁ1対多のモデルの関連づけの話しだから当然必要。
あくまでもおおまかな説明なので参考にする方にはすみません。
コードはまた別で投稿してあります。
2.次にフォローされることのみを考えたモデルの関連を考える。
簡単に言えば、passive_relationship.~
メソッドを作成することである。
例えば、passive_relationship.follower
で、
あるユーザーAをフォローしているユーザーを返すメソッドなどである。
ここまではフォローすることとフォローされることの動的関係を行うためのモデルの関連付けをした。
次からは上の定義したもので行われたフォローとフォロワーの集団を取り出す定義をする。
まず前提としては1人のユーザーにはいくつもの「フォローする/される(多対多)」のリレーションがある。
あるユーザーがフォローしている集団を取り出す定義
has_many :following, through: :active_relationships, source: :following
この定義によってuser.followingで、あるユーザーAがフォローしている集団を取り出すことができるようになる。
あるユーザーのフォロワーの集団を取り出す定義
has_many :followers, through: :passive_relationships, source: :follower
これを定義することよって、
user.followersで、あるユーザーAをフォローしている集団(フォロワー)を取り出すことができるようになる。
ここがわかりにくいところで、本来のhas_many throughならば3つのモデルがあるので、これらの対になっている定義は別のモデルに書くはずだが、
これらの定義は両方とも同じモデルで定義されているので非常にわかりにくいので注意。