環境
Rails6,
MySQL
状況
マイグレーションファイルを書き、マイグレートすると、以下のようなエラー文が表示されました。
Caused by:
ActiveRecord::MismatchedForeignKey: Column `food_id` on table `orders` does not match column `id` on `foods`, which has type `bigint(20)`. To resolve this issue, change the type of the `food_id` column on `orders` to be :bigint. (For example `t.bigint :food_id`)
要するに、参照されるカラムの型と、参照する側のカラムの型が一致しないので、外部キー設定ができないと表示されています。
解決した方法
エラー文から、原因はカラムの型と思いましたが、マイグレーションファイルを作成した順番が原因でした。
簡略化したコードで説明します。
temporary_ordersと、ordersという二つのテーブルがあり、
それぞれ、以下のマイグレーションファイルになっていました。(テーブル名は今回のエラーに関連しません。)
class CreateTemporaryOrders < ActiveRecord::Migration[6.0]
def change
create_table :temporary_orders do |t|
t.references :order, foreign_key: true
end
end
end
class CreateOrders < ActiveRecord::Migration[6.0]
def change
create_table :orders do |t|
t.integer :price, null: false
end
end
end
今回のエラーに関わる知識として、migrationファイルがマイグレートされる時は、作成された時
間が古いファイル、つまり、ファイル名の先頭の数字が小さいものから、順にマイグレートされます。
例のtemporary_ordersファイルと、ordersファイルを比較すると、temporary_ordersファイルの方が、ファイル名の先頭の数字が小さいことから、先に作成していることが分かります。
なので、マイグレートされる順番は、先にtemporary_ordersファイルで、次にordersファイルです。
ここで、temporary_ordersファイルに以下のコードがあります。
t.references :order, foreign_key: true
これをみると、temporary_ordersファイルがマイグレートされる時には、ordersファイルはまだ、マイグレートされていないにもかかわらず、ordersテーブルから、外部キーを参照しようとし
ています。これがエラーの原因でした。
つまり、referencesで外部キーを参照し、マイグレートした時、参照元のカラムが存在しないのに、参照しようとしていたことが原因でした。
まとめ
このエラー文を見ると、カラムの型が原因と思い、カラムの型をtypeで指定したり、migrationファイルのバージョンを変えてみたりしましたが、原因はカラムの型ではありませんでした。
エラー文が必ず、正しい原因を指摘してくれるわけではないことが分かりました。
以上です。
勉強になった記事
https://qiita.com/nkekisasa222/items/84c257fc1a8ae964ddb9