LoginSignup
4
2

More than 3 years have passed since last update.

rails5.1以降へのバージョンアップ時に、migrationのFK制約が貼れず躓いた話

Last updated at Posted at 2019-09-16

rails5.1以降で外部キーの仕様変更でコケてしまったので備忘録として。

エラー内容・エラーに至るまでの経緯

エラーが起きたのは、railsを5.0から5.2にバージョンアップ後、
rails db:migrateした時でした。
ターミナル上のエラー文は以下です。

bash
-- 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ファイルは以下です

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ファイルなどのバージョンも確認しよう

4
2
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
4
2