同じモデルに対する外部参照キーを別名で複数持つ方法
同じモデルに対する外部参照キーを複数持つ方法
今週に入って、だいたい10度前後を推移していた(高い時は20度近かった)のに、この日の最高気温2度。
寒すぎ。
どうでもいいですね。
さて、今回は同じモデルに対する外部参照キーを複数持つ方法、そして外部参照キーの名前をデフォルトから変更する方法を一気にやります。
言葉だけだとわかりにくいのでイメージを説明します。
何がしたいのか
あるユーザが複数のPostを持っているようなモデルを想像する。
誰から誰に投稿したのか、どのグループに投稿したのかを保持したくて
- from_user_id
- to_user_id
- posted_group_id
を持たせた。
from_user_id
と to_user_id
がともにUserを参照してほしい。
という感じです。
HOW TO
テーブル作成時にカラム名を変更しておく
外部参照をするときは、
class CreatePosts < ActiveRecord::Migration[5.1] def change create_table :posts do |t| t.string :text t.references :user, foreign_key: true t.timestamps end end end
のように書くのがオーソドックス。
そして実際に作成されるテーブルには user_id
でカラムが作成される。
ただ今回みたいに from_user_id
と to_user_id
という別々のカラムを作成し、それぞれでUserを参照したい場合、同じカラムがPostsテーブル内に2つ存在することになるので困る。
なので user_id
というカラムを作るのをやめてもらう。
class CreatePosts < ActiveRecord::Migration[5.1] def change create_table :posts do |t| t.string :text t.references :from_user, foreign_key: { to_table: :users } t.references :to_user, foreign_Key: { to_table: :users } t.timestamps end end end
このように書くことで、Postsテーブルには from_user_id
と to_user_id
というカラムができる。
これでOK。マイグレートする。
Modelにアソシエーションを追加
もちろんこれだけではダメで、Modelにアソシエーションを記載しないといけない。
class Post < ApplicationRecord belongs_to :from_user, class_name: 'User', :foreign_key => 'from_user_id' belongs_to :to_user, class_name: 'User', :foreign_key => 'to_user_id' has_many :praise_replies end
アソシエーションを記述する際は、 belongs_to :${table_name}
がオーソドックスだが、今回はUserを参照しているカラムが2つあるのでそれぞれに対してアソシエーションの定義が必要。
これで例えば
posts = Post.all.includes(:from_user) posts.each do |post| puts post.from_user.name puts post.from_user.email end
とするとPostに紐づくfrom_userのUser情報をワンクエリで取ってくることができる。
以上です。
いつもこれくらいサバサバした文章を書きたいな。。。
ありがとうございました。