先日、どうしてもテーブルの主キーをID以外に変えなければならない状況になり、依存関係もあるテーブルの主キーを変更したのですが、個人的にはかなり躓いてしまったので、手順をメモします。
やったこと
実施したことは以下の通り。
- マイグレーションファイルを変更(参照先テーブル、参照元テーブル)
- モデルの変更(参照先テーブル、参照元テーブル)
なお、環境は以下の通り
- Rails 5.2.4.2
- Postgresql 12.2
マイグレーションファイルの変更
参照先テーブルの設定
officesテーブルに従属するstaffsテーブルがあったとします。
officesテーブルの主キーはoffice_code
とします。
この時officeテーブルを作成するマイグレーションの設定は下記のとおりです。
class CreateOffices < ActiveRecord::Migration[5.2]
def change
create_table :offices, id: false do |t| # id: falseを追加
t.string :name, null: false
t.integer :office_code, null: false, primary_key: true # primary_key: trueを追加
t.timestamps
end
end
end
id: false
で自動で主キーをIDにする設定を解除します。
次に、primary_key: true
で明確にoffice_code
を主キーに設定します。
参照される側のテーブルの設定はこれで終わりです。
参照元テーブルの設定
次に、staffs
テーブルからoffice
テーブルをoffice_code
という外部キーで参照したいと思います。
この時のマイグレーションファイルの設定は下記のとおりです。
class CreateStaffs < ActiveRecord::Migration[5.2]
def change
create_table :staffs do |t|
t.string :name, null: false
t.references :office, null: false #foreign_key: true は設定しない
t.timestamps
end
add_foreign_key :staffs, :offices, column: :office_code , primary_key: :office_code
# ここで外部キーを設定
end
end
t.references :office
でofficesテーブルを参照することを宣言しますが、ここでforeign_key: true
を設定しないのがポイントです(ここでだいぶはまった…)。
foreign_key: true
を設定するとoffice_id
を参照し続けてしまいます。
そして、マイグレーションファイルの下方に
add_foreign_key :参照元テーブル, :参照先テーブル, column: :参照するカラム , primary_key: :参照するテーブルの主キー
を記述します。
モデルの変更(参照先テーブル、参照元テーブル)
参照先テーブル
参照先テーブルであるoffice.rb
のモデルファイルの設定は下記の通り。
class Office < ApplicationRecord
self.primary_key = :office_code # ここに追記
has_many :staffs
validates :name, presence: true
validates :office_code, presence: true
end
まず、self.primary_key = 'カラム名'
で主キーを設定します。
これによってfindメソッドでoffice_code
による検索が可能になります。
参照元テーブル
最後に、offices
テーブルを参照しているstaffs
テーブルのモデルの記載について
class Staff < ApplicationRecord
belongs_to :office, primary_key: :office_code # ここに追記
validates :office_id, presence: true
validates :name, presence: true, length: { maximum: 50 }
end
primary_key: :office_code
の部分で、staffsテーブルからデータを参照するときの主キーを:office_code
に変更します。
上記で、無事、依存関係のあるテーブルにおいて、主キーをIDから変更し、アソシエーションを定義することができました。
まだ理解があいまいな点もあるので、間違いを発見したら修正していこうと思います。
参考情報
Railsで規約に沿わない古いデータを扱う
[Rails] 主キーがid以外のテーブルを外部キーに設定する方法
Active Record の関連付け
Rails で id 以外を主キー(primary_key)に設定する