Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?
@aseanchild1400

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

More than 1 year has passed since last update.

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

2
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
aseanchild1400
備忘録多めです

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
2
Help us understand the problem. What is going on with this article?