モデル名と異なるアソシエーション名を使う場合の決まり
Rails tutorialでも出てくるuserがfollowings/followers(どちらもuserテーブルを使う)を持つ関係を例にまとめる。
models/user.rb
class User < ApplicationRecord # followingsのアソシエーション has_many :relationships has_many :followings, through: :relationships, source: :follow # followersのアソシエーション has_many :reverses_of_relationship, class_name: 'Relationship', foreign_key: 'follow_id' has_many :followers, through: :reverses_of_relationship, source: :user end
中間テーブルはrelationshipsとする。
models/relationship.rb
class Relationship < ApplicationRecord belongs_to :user belongs_to :follow, class_name: 'User' end
class_nameについて
モデル名_id という名前になっている場合、Railsでは自動的にモデルを参照する。
しかし follow_id のように命名規則に従っていないものを使う場合は、 class_name: 'User'
と補足設定する必要がある。
through, sourceについて
既存のリレーションから中間テーブルを経由して向う側にあるモデルを参照するようにするためには、 through: ... , source: ...
を使用する。
has_many :followings, through: :relationships, source: :follow
これにより、 user.followingsと書けば、該当のuser がフォローしている User群を取得できるようになる。
仕組み
has_many :followings
- usersとfollowingsの関係を新しく命名し、フォローしているUser群を表現している。
- Followingというモデルは無いため、この後ろに取得する情報の補足を付け足している。
through: :relationships
- has_many: relationshipsの結果を中間テーブルとして指定している。
source: :follow
- 中間テーブルのカラムの中でどれを参照先の id とすべきかを選択している。
- user_id というカラム名にすると重複してしまう為、フォローされる側は follow_id とする
上の仕組みによって、 user.followingsでuser が中間テーブル relationships を取得し、
その1つ1つの relationship の follow_id から 自分がフォローしている User 達 を取得する流れができる。
models/user.rbに見やすく色をつけるとこんな感じ。
has_many :relationships
has_many :followings, through: :relationships, source: :follow
has_many :reverses_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id'
has_many :followers, through: :reverses_of_relationship, source: :user