LoginSignup
0
0

More than 3 years have passed since last update.

referencesで外部キー設定をしたら、ActiveRecord::MismatchedForeignKeyで詰まった時の解決法(Rails)

Last updated at Posted at 2021-02-24

環境

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という二つのテーブルがあり、
それぞれ、以下のマイグレーションファイルになっていました。(テーブル名は今回のエラーに関連しません。)

migrate/20210223101010_create_temporary_orders.rb
class CreateTemporaryOrders < ActiveRecord::Migration[6.0]
  def change
    create_table :temporary_orders do |t|
      t.references :order, foreign_key: true
    end
  end
end

migrate/20210223113122_create_orders.rb
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

0
0
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
0
0