関連付けアンチだったけど、今は好き。「コロンが付いたら配列を疑え」の意識がまた消えてた。でもモデルに関しての知識が深まったから良し(?)。普通にreferences使わない方が簡単。
####【ページ内リンク】
0.環境
1.動機
2.やった
3.foreign_key: trueを設定する理由
4.感想
5.参考文献
#0.環境
・AWS
・heroku/7.48.0 linux-x64 node-v12.16.2
・Rails 5.2.4.5
・ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]
・MySQL 5.7.31
・PostgreSQL 9.2.24
#1.動機
試合のテーブル(Gameテーブル)を作っている。試合なのでホームチームとビジターチームの2種類のチーム名が必要。Teamテーブルと関連付けしたいが、Gameテーブルにhometeam_id
、visitorteam_id
を作った場合、belongs_to
でTeamテーブルのid
とどうやって関連付けすればいいんだ・・・?と思ったため
#2.やった
【やりたいこと】
①カラム名をhometeam_id
、visitorteam_id
とする
②外部キー制約
③game.hometeam.~
で値が取れるようにする
④値がnullでもOKとする
class CreateGames < ActiveRecord::Migration[5.2]
def change
create_table :games do |t|
t.references :hometeam, foreign_key: { to_table: :teams }
t.references :visitorteam, foreign_key: { to_table: :teams }
t.timestamps
end
end
end
・t.references :hometeam
で、hometeam.id
の値を参照しますよという意味(しかし、そんな物は無い。) #①完了
・foreign_key: { to_table: :teams }
は、foreign_key: true
を変形したもの。なぜtrue
だと駄目なのかは、t.references :hometeam, foreign_key: true
だとhometeamテーブル
と外部キー制約をするということになる。しかしそんなテーブルは存在せず、teamテーブル
を参照する必要があるから。 #②完了
class Game < ApplicationRecord
belongs_to :hometeam, class_name: "Team", optional: true
belongs_to :visitorteam, class_name: "Team", optional: true
end
・optional: true
は下記参照。 #④完了(?)
・【belongs_to :hometeam
でgame.hometeam
としたときに値が取れるようにし、class_name: "Team"
で値はteamテーブル
から取りましょう。という意味。】 #③完了
#3.foreign_key: true
を設定する理由
外部キー制約をするため。
foreign_key: true
が無い場合を考える。references
クラスとすると、値が親テーブルに無かったりnullの場合にエラーを出す。
値がnullでもOKとしたい場合はoptional: true
を入れるが、これだと親テーブルに無い値の時にもエラーを吐き出さずに通してしまう。
foreign_key: true
を入れることで、親テーブルに無い値の時はエラー、nullはOKとなる。
※値がnullでエラーとするときの存在価値は正直分からなかった。references
と役割が被っているのか、それとも何か別の理由があるのだろうか。もしくは自分がただ勘違いしているのか。
#4.感想
③について思ったこと。
普段はbelongs_to :team
のように関連付けを行っているけど、これってclass_name
を指定しない場合は自動でclass_name: "Team"
となってるだけなのかな。何でTeamテーブル
を参照しているのにbelongs_to Team
じゃないんだろうと思ってたけど、なるほど合点がいった。Railsすごい(n回目)
#5.参考文献
参考1:Railsで外部キー制約のついたカラムを作る時のmigrationの書き方
参考2:Active Record の関連付け