LoginSignup
50
42

More than 5 years have passed since last update.

[Rails] 我初心者、foreign_keyの定義がわからなかったので自分なりに噛み砕いてみた

Last updated at Posted at 2019-03-26

目標

has_manyの関連付けを作成するときに、
どちらのモデルに対してforeign_keyを指定するべきか
わからず調べたものの、その説明すらわかりにくかったので
自分なりの解釈を載せていこうと考えた。。

疑問

今、User has_many cupsという関係を作りたいとする。

[モデルの関係]
User

↓ has_many

Cup

// Cupとはコーヒーカップのことでここでは「コーヒー」という意味
// User has_many cupsってお前一日に何杯飲むねんって感じだけど。。


この場合、UserCup、どっちのマイグレーションファイルに
foreign_keyを記載すればいいの?

そもそもforeign_keyってなんなのかわかってないなあ。調べよ

foreign_keyとは?(わかりにくい)

foreign_key
参照先を参照するための外部キーの名前を指定するもの

※以下より引用
http://railsdoc.com/references/belongs_to

わかりづれ〜〜〜(^ー;)

参照先を参照するって、
has_manyで参照する場合を示すのか、
belongs_toで参照する場合を示すのか
どっちよこれ。。

改めてforeign_keyとは?(わかりやすい)

ズバリ言うと(結果論)、この文脈においてはbelongs_toで参照する場合を示す。

従って、先ほどの文は

foreign_key
belongs_toによって)参照先を参照するための外部キーの名前を指定するもの

という解釈になる。

加えて、相手(参照先)の外部キーの名前を指定するものってことだから、
それはbelongs_toを行う側に記述しなければいけないってことも読み取れる。

よって、この文は

foreign_key
belongs_toで参照する相手(参照先)の外部キーを指定するために、
belongs_toを行う側に記述しなければならないもの

と解釈できる。

マイグレでforeign_keyを指定する際の注意点

マイグレーションファイルの作成時に、
foreign_keyの指定をするコードには、

  def change
    create_table AAAA do |t|
       t.references BBBB, foreign_key: true
    end
  end

とか

  def change
    add_reference AAAA, BBBB, foreign_key: true
  end

という形をとるものがあり、どちらも

テーブルAAAAに、 モデルBBBBのforeign_key(= BBBB_id) を追加する

と解釈される。

しかしこれだと、このBBBB_idを追加したものの、
それをhas_manyで参照するのか、
belongs_toで参照するのかって話になる。


先ほどのforeign_keyの話に戻すと、
foreign_keyは、belongs_toを行う側に記述しなければならないものであった。

上記のコードでは、create_table AAAAという記載から
AAAAというテーブルにBBBBへのforeign_keyを指定する
という意味になるので、

AAAA belongs_to BBBB

という関係になっていることがわかる。

そしてこれは

BBBB has_many AAAA

という関係でもある。(has_manyの場合は)

結論

つまり、BBBB has_many AAAAという関連付けをしたい場合、
foreign_keyAAAAに指定しなければいけないということ。
(正確に言うと、AAAAのテーブルを編集するマイグレファイルに記述しなければならない


理由は(くどいが)、foreign_keybelongs_toで参照を行う側に記述しなければならないため、
上記関連付けをAAAA belongs_to BBBBという形に直したときに、
belongs_toを行っているのはAAAAなので、AAAA側に記述する。


ちなみに(追記)

foreign_keyを記述してrails db:migrateをすると、
foreign_keyを記述した側のモデル.rbに自動的にbelongs_toが記述されます。
has_manyに関してはもう片方のモデル.rbに手で記述しなければなりません)

このことからも、foreign_keybelongs_toで参照するという前提が正しいことがわかりますね。


終わり

50
42
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
42