rails5.1以降で外部キーの仕様変更でコケてしまったので備忘録として。
#エラー内容・エラーに至るまでの経緯
エラーが起きたのは、railsを5.0から5.2にバージョンアップ後、
rails db:migrate
した時でした。
ターミナル上のエラー文は以下です。
-- create_table(:tours, {:options=>"ENGINE=InnoDB", :id=>:integer})
rails aborted!
StandardError: An error has occurred, all later migrations canceled:
Column `user_id` on table `tours` does not match column `id` on `users`,
which has type `bigint(20)`.
To resolve this issue,
change the type of the `user_id` column on `tours` to be :bigint.
(For example `t.bigint :user_id`).
Original message: Mysql2::Error: Cannot add foreign key constraint:
CREATE TABLE `tours` (`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY, `tourname` varchar(255),
`tourcontent` text, `user_id` int, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL,
INDEX `index_tours_on_user_id` (`user_id`), CONSTRAINT `fk_rails_644aa67ccf`
FOREIGN KEY (`user_id`)
REFERENCES `users` (`id`)
) ENGINE=InnoDB
Caused by:
Mysql2::Error: Cannot add foreign key constraint
また、toursテーブル作成時のmigrationファイルは以下です
# frozen_string_literal: true
class CreateTours < ActiveRecord::Migration[5.0]
def change
create_table :tours do |t|
t.string :tourname
t.text :tourcontent
t.references :user, foreign_key: true
t.timestamps
end
add_index :tours, %i[user_id created_at]
end
end
#rails5.1以降はreferenceがbigint型で生成される
エラー文をざっと読んでみたところ
Column `user_id` on table `tours` does not match column `id` on `users`,
which has type `bigint(20)`.
To resolve this issue,
change the type of the `user_id` column on `tours` to be :bigint.
(For example `t.bigint :user_id`).
ここらへんがエラーの原因&解決策っぽいですね。
「toursテーブルのuser_idカラムがuserテーブルのidと一致しません。user_idはbigint型です。解決するために、toursテーブルのuser_idをbigint型にしてください」
という意味だと解釈。
え、user_idってinteger型じゃないの??と疑問に思ったのですが、
Rails 5.1以前に作成されたテーブルにFK制約を張れない問題の解決策
バッチリ書いてありました。。。rails5.1以降はuser_idのようなカラムがbigint型で生成されるとのことでした。
外部キーエラーの原因なんですが、今回の場合だと、usersテーブルのid(bigint型)とtoursテーブルのuser_id(integer型)の異なる型を持つカラムが混在している状況なので、整合性が取れず、FK制約が貼れないらしいです。
#railsバージョンアップ時はmigrationファイルのバージョンも確認しよう
しかし、toursテーブルのuser_idがinteger型になっていたのはなぜだろうと考えていたところ、有識者の方からmigrationファイル内で継承元クラスのActiveRecord::Migration[5.0] と ActiveRecord::Migration[5.2]が混在しているとご指摘をいただきました。
railsをバージョンアップした際に、migrationファイルのバージョンを確認できていなかったようです...
指摘して頂いたとおりに、バージョンを訂正したところ無事想定どおりの動きをしてくれるようになりました。
感謝!!
#まとめ
・rails5.1以降はreferenceがbigint型で生成される
・railsバージョンアップ時はmigrationファイルなどのバージョンも確認しよう