はじめに
ローカル環境で db:migrate
を実行したところ、突然以下のエラーが発生しました
Column `application_id` on table `oauth_access_grants` does not match column `id` on `oauth_applications`, which has type `bigint(20)`. To resolve this issue, change the type of the `application_id` column on `oauth_access_grants` to be :bigint. (For example `t.bigint :application_id`).
Original message: Mysql2::Error: Cannot add foreign key constraint
日本語訳
テーブル `oauth_access_grants` の `application_id` カラムは `oauth_applications` の `id` カラムと一致しません。この問題を解決するには、`oauth_access_grants` の `application_id` カラムの型を :bigint 型に変更します。(例: `t.bigint :application_id`).
元のメッセージ Mysql2::Error: 外部キー制約を追加できません
検証環境
- Rails 7.0.2
- MySQL 5.7.30
- Gem
- doorkeeper 5.5.4
調べてみた
2つのテーブルのマイグレーションは以下のように定義されています
create_table :oauth_applications, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.string :name, null: false
t.string :uid, null: false
t.string :secret, null: false
# Remove `null: false` if you are planning to use grant flows
# that doesn't require redirect URI to be used during authorization
# like Client Credentials flow or Resource Owner Password.
t.text :redirect_uri, size: :medium, null: false
t.string :scopes, null: false, default: ''
t.boolean :confidential, null: false, default: true
t.timestamps null: false
end
add_index :oauth_applications, :uid, unique: true
create_table :oauth_access_grants, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.references :resource_owner, null: false
t.references :application, null: false
t.string :token, null: false
t.integer :expires_in, null: false
t.text :redirect_uri, size: :medium, null: false
t.datetime :created_at, null: false
t.datetime :revoked_at
t.string :scopes, null: false, default: ''
end
実際のテーブルを確認してみると oauth_applications.id
カラムの型は bigint
、oauth_access_grants.application_id
の型はint
で作成されていた。それはおかしい!
Doorkeeper側で何か変更があったのか調べてみたのですがそれらしい情報が見当たらない。はて、これはいったい・・・。
原因
Rails 7.0.1 に入っていたこれが原因でした。
Fix migration compatibility to create SQLite references/belongs_to column as integer when migration version is 6.0.
Reference/belongs_to in migrations with version 6.0 were creating columns as bigint instead of integer for the SQLite Adapter.
Marcelo Lauxen
migration version 6.0 が指定されている場合、 references指定で作成される型が bigint から int 型に変更されていました。これの影響で型の不一致が発生していました。
解決策
対象のマイグレーションファイルのmigartion versionを 6.0 から 6.1 に変更すれば db:migrate
が正常に通るようになります!
- class CreateDoorkeeperTables < ActiveRecord::Migration[6.0]
+ class CreateDoorkeeperTables < ActiveRecord::Migration[6.1]
まとめ
過去にも何回かマイグレーションが通らない問題にぶつかった時も Rails のバージョンアップだったので、メジャーバージョンアップ時は一度はマイグレーションを実行してみようという学びを得ました。