Railsで別名の外部キーを設定する方法


Railsで別名の外部キーを設定する方法

1対多のリレーションで別名の外部キーのカラム名を設定した記録です。

背景

通常、1対多のリレーションではTeamモデルにはuserと書くことが多いが、
Teamの所有者であることを強調したいので別名カラムownerを設定する必要がありました。

目次


動作環境

OS : macOS Mojave 10.14.6
ruby : 2.6.3p62
rails : 5.2.4

結論

以下のステップで実現できました。

STEP1.別名カラムをTeamsモデルに作成

マイグレーション

1. 新規テーブルの場合

migrationfile1.rb
class CreateTeams < ActiveRecord::Migration[5.2]
  def change
    create_table :teams do |t|
      t.string :name
      t.integer :owner_id, index: true

      t.timestamps
    end
    add_foreign_key :teams, :users, column: :owner_id
  end
end

2. 既存テーブルに追加する場合

migrationfile.rb
class AddUserRefToTeams < ActiveRecord::Migration[5.2]
  def change
    add_reference :teams, :owner, foreign_key: { to_table: :users }
  end
end

マイグレーションの実行

rails db:migrate
schema
  create_table "teams", force: :cascade do |t|
    t.string "name"
    t.integer "owner_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "icon"
    t.index ["owner_id"], name: "index_teams_on_owner_id"
  end

  add_foreign_key "teams", "users", column: "owner_id"

STEP2.UserモデルとTeamモデルにリレーションを設定

user.rb
class User < ApplicationRecord
  has_many :teams, foreign_key: :owner_id
end
team.rb
class Team < ApplicationRecord
  belongs_to :owner, class_name: 'User', foreign_key: :owner_id
end

結果

以下のようにteam.ownerでチーム所有者のuser情報が取り出せています。

ポイント

リレーションにクラス名をつけること

userカラムの場合はteamモデルにclass_nameはつけませんが、
別名の場合はclass_nameをつけないとエラーになってしまいました。

belongs_to :owner, class_name: 'User', foreign_key: :owner_id

おわりに

今回の件で以下のことを学びました。
別名外部キーの設定方法