dev/mom0tomo

技術メモ

モデル名と異なるアソシエーション名を使う場合の決まり

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