概要
rails5.0からrails5.2にバージョンを上げた時にマイグレーションが失敗するようになったので,原因の調査と解決を行なった.
原因
出力されたエラーは以下で,エラーを読むと,usersテーブルのidをmicropostsテーブルのuser_idの外部キーとして設定することに失敗したことが分かりました.
ActiveRecord::StatementInvalid: Mysql2::Error: Referencing column 'user_id' and referenced column 'id' in foreign key constraint 'fk_rails_558c81314b' are incompatible.: ALTER TABLE `microposts` ADD CONSTRAINT `fk_rails_558c81314b`
FOREIGN KEY (`user_id`)
REFERENCES `users` (`id`)
...
Caused by:
Mysql2::Error: Referencing column 'user_id' and referenced column 'id' in foreign key constraint 'fk_rails_558c81314b' are incompatible.
原因となっているusersテーブルとmicropostsテーブルのスキーマを調べたところ,userテーブルのidはbigint型,micropostsテーブルのuser_idはint型となっており,型が一致していませんでした.
これはrails5.1からテーブルのidカラムがbigintになったことによって起きたことでした.
mysql> show create table users \G;
*************************** 1. row ***************************
Table: users
Create Table: CREATE TABLE `users` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`password_digest` varchar(255) DEFAULT NULL,
`remember_digest` varchar(255) DEFAULT NULL,
`admin` tinyint(1) DEFAULT '0',
`activation_digest` varchar(255) DEFAULT NULL,
`activated` tinyint(1) DEFAULT '0',
`activated_at` datetime DEFAULT NULL,
`reset_digest` varchar(255) DEFAULT NULL,
`reset_sent_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index_users_on_email` (`email`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> show create table microposts \G;
*************************** 1. row ***************************
Table: microposts
Create Table: CREATE TABLE `microposts` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`content` text,
`user_id` int(11) DEFAULT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`picture` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_microposts_on_user_id_and_created_at` (`user_id`,`created_at`) USING BTREE,
KEY `index_microposts_on_user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
解決策
今回は外部キーであるuser_idの型をbigintに変更することで対応しました.
具体的な対応としては,schema.rbを以下のように変更しました.
create_table "microposts", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
...
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
...
end
↓
create_table "microposts", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
...
t.bigint "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
...
end
この後,rails db:setup
を実行することで,無事マイグレーションが成功するようになりました.
参考
こちらの記事を参考にさせていただきました.