Railsでお知らせ機能やフォロー機能を実装しているとclass_nameやforeign_keyが出てくると思います。これらを理解するのに時間がかかったので、備忘録もかねて投稿します。
今回はお知らせ機能を例に挙げる。
イメージしやすいようER図を載せる。(最低限のカラムしか書いてません。)
お知らせ機能を実装していると@user.passive_notificationsのようにして自分に来ている通知のレコードをまとめて取得したいことがある。そういう場合、下のように書く。
has_many :passive_notifications, class_name: "Notification", foreign_key: "visited_id"
少し複雑なので、簡単な例を挙げる。
Userモデルで下記のように定義した場合
よく使うhas_many :tweetsは実は色々省略されている。
has_many :tweets
# 同じ意味
has_many :tweets, class_name: "Tweets", foreign_key: "user_id"
Railsで開発をするとhas_manyやbelongs_toを使ってモデルでリレーションを組むが、これを書くことによって、Userクラスへのticketsメソッドの定義が裏で行われている。例でいうと、ticketsメソッドの対象となるClassはTweetクラスで、ticketsテーブルのuser_idの値を参照してレコードを取得する。
Railsの規則によりモデルの複数形でメソッドを定義する場合、クラス名、外部キーを省略することができる。なぜならメソッド名により暗黙的にクラス名、外部キーが決定されるからである。
上記のようにメソッドを定義する(リレーションを組む)ことで、コントローラーなどで下のメソッドが使えるようになる。
@user = User.find(params[:id])
@user.tweets
少し脱線したが、このことを頭に入れてお知らせ機能のリレーションをもう一度見てみる。
has_many :passive_notifications, class_name: "Notification", foreign_key: "visited_id"
ここの記述では、Userモデルにpassive_notificationsメソッドを定義している。
メソッド名からはクラス名が不明なため、class_name: "Notification"として対象のクラスを明示している。また、外部キーを設定しない場合、notificationsテーブルからuser_idのカラムを探しにいってしまうため、foreign_key: "visited_id"として定義する。
これにより、@userのidとnotificationsテーブルのvisited_idとが一致したレコード、つまり@user宛の通知のレコードがまとめて取得できるようになる。
@user = User.find(params[:id])
@user.passive_notifications #ユーザ宛の通知のレコードを全件取得
以上です。
まちがっていたらご指摘お願いします。