3
1

More than 1 year has passed since last update.

Rails 7でテーブルカラムの型不一致による外部キー追加エラーが発生した場合の解決方法

Last updated at Posted at 2022-02-10

はじめに

ローカル環境で db:migrate を実行したところ、突然以下のエラーが発生しました :thinking:

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 カラムの型は bigintoauth_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 が正常に通るようになります! :tada:

- class CreateDoorkeeperTables < ActiveRecord::Migration[6.0]
+ class CreateDoorkeeperTables < ActiveRecord::Migration[6.1]

まとめ

過去にも何回かマイグレーションが通らない問題にぶつかった時も Rails のバージョンアップだったので、メジャーバージョンアップ時は一度はマイグレーションを実行してみようという学びを得ました。

3
1
1

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
3
1