関連付けアンチだったけど、今は好き。「コロンが付いたら配列を疑え」の意識がまた消えてた。でもモデルに関しての知識が深まったから良し(?)。普通に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 の関連付け