【Rails】foreign_keyの挙動を確認してみた【Active Record】

Ruby

動作確認環境

  • Windows10(x64)
  • Rails 6.1.7.3
  • 3.0.4p208

下記のようにusersテーブルとcompaniesテーブルがあり外部キーが定義されている

外部キーの名前はrailsの命名規則(company_id)に則っていないようなケースでhas_manyとbelongs_toによる関連付けを行うケースを想定する。

うまくいくケース(双方のモデルから紐づくレコードを取得できる)

双方のモデルにforeign_keyオプションを設定

class Company < ApplicationRecord
  has_many :users, foreign_key: :kaisha_id
end
class User < ApplicationRecord	
  belongs_to :company, foreign_key: :kaisha_id	
end

上記のようなモデルを用意し、rails c で下記のコマンドを実行し、紐づくレコードを取得できるか確認した

u = User.find(1)
u.company
c = Company.find(1)
c.users.first

結果としては

  • u.companyを実行すると紐づくレコードを取得できた。
  • c.users.firstを実行すると紐づくレコードを取得できた。

class_nameオプションとforeign_keyオプションを併用

class Company < ApplicationRecord
  has_many :users, foreign_key: :kaisha_id
end
class User < ApplicationRecord
  belongs_to :kaisha, class_name: :Company
end

上記のようなモデルを用意し、rails c で下記のコマンドを実行し、紐づくレコードを取得できるか確認した

u = User.find(1)
u.kaisha
c = Company.find(1)
c.users.first

結果としては

  • u.kaishaを実行すると紐づくレコードを取得できた。
  • c.users.firstを実行すると紐づくレコードを取得できた。

うまくいかないケース

オプションを何も設定しない

kaisha_idが命名規則の則っていないのでうまくリレーションを取得できない

class Company < ApplicationRecord	
  has_many :users	
end	
class User < ApplicationRecord	
  belongs_to :company	
end

上記のようなモデルを用意し、rails c で下記のコマンドを実行し、紐づくレコードを取得できるか確認した

u = User.find(1)
u.company
c = Company.find(1)
c.users.first

結果としては

  • u.companyを実行するとnilが返却される
  • c.users.firstを実行するとusers.company_idカラムが存在しない、というようなエラーが表示される

has_many側にだけforeign_keyを設定

class Company < ApplicationRecord	
  has_many :users, foreign_key: :kaisha_id	
end
class User < ApplicationRecord	
  belongs_to :company	
end

上記のようなモデルを用意し、rails c で下記のコマンドを実行し、紐づくレコードを取得できるか確認した

u = User.find(1)
u.company
c = Company.find(1)
c.users.first

結果としては

  • u.companyを実行するとnilが返却された
  • c.users.firstは紐づくレコードを取得できる

belongs_to側にだけforeign_keyを設定

class Company < ApplicationRecord	
  has_many :users	
end
class User < ApplicationRecord	
  belongs_to :company, foreign_key: :kaisha_id	
end

上記のようなモデルを用意し、rails c で下記のコマンドを実行し、紐づくレコードを取得できるか確認した

u = User.find(1)	
u.company	
c = Company.find(1)	
c.users.first

結果としては

  • u.companyを実行すると紐づくレコードを取得できた。
  • c.users.firstを実行するとusers.company_idがない旨のエラーが表示された。
タイトルとURLをコピーしました