0
0

Rails5.1以前と以降のデータ型の違いによるマイグレーションエラーの解決方法

Posted at

はじめに

Rails6.1でreferencesを使って既存のテーブルを参照する新しいテーブルを作成しようとした際、エラーに遭遇しました。

エラーの内容とその原因・解決方法をまとめます。

エラーの概要

やりたいこと

既存のUserテーブルを参照して新たにSocialLink(SNSなどの外部サービスのリンクを保持する)テーブルを作成したい。

使用したマイグレーションファイル

class CreateSocialLinks < ActiveRecord::Migration[6.1]
  def change
    create_table :social_links do |t|
      t.references  :user, null: false, foreign_key: true
      t.string      :type, null: false
      t.string      :url,  null: false

      t.timestamps
    end
  end
end

rails db:migrate実行時に発生したエラー

Mysql2::Error: Referencing column 'user_id' and referenced column 'id' in foreign key constraint 'fk_rails_a95eea6600' are incompatible.

エラーの原因

Railsのバージョンによる主キーや外部キーのデータ型の違いが原因でした。

  • Rails5.1 より前: 主キーと外部キーはinteger
  • Rails5.1 以降: 主キーと外部キーはbigint

今回のケースは

  • Userテーブル:Rails 4で作成(idinteger型)
  • SocialLinkテーブル:Rails 6.1で作成(user_idbigint型)

そのため、UserテーブルのidカラムとSocialLinkテーブルのuser_idカラムのデータ型が不一致となりエラーが生じていました。

解決策

以下の2つの解決策があります。

  1. SocialLinkテーブルのuser_idカラムをinteger型に変換する
  2. Userテーブルのidカラムをbigint型に変更する

1. SocialLinkテーブルのuser_idカラムをinteger型に変換する

referencesを使って外部キー制約をつける場合、以下のようにtype: :integerを書けばOKです。

class CreateSocialLinks < ActiveRecord::Migration[6.1]
  def change
    create_table :social_links do |t|
      # type: :integer を追加
      t.references  :user, null: false, foreign_key: true, type: :integer
      t.string      :type, null: false
      t.string      :url,  null: false

      t.timestamps
    end
  end
end

もしくは、referencesを使用せず、user_idinteger型で定義し、add_foreign_keyで外部キーを別途つけても問題ありません。

class CreateSocialLinks < ActiveRecord::Migration[6.1]
  def change
    create_table :social_links do |t|
      # user_id カラムを追加
      t.integer  :user_id, null: false
      t.string   :type,    null: false
      t.string   :url,     null: false

      t.timestamps
    end
    # 外部キー制約を別途付与
    add_foreign_key :social_links, :users
  end
end

2. Userテーブルのidカラムをbigint型に変更する

この場合、まずchange_columnUserテーブルのidカラムのデータ型を変更するマイグレーションファイルを実行します。

class ChangeUsersId < ActiveRecord::Migration[6.1]
  def up
    # int から bigint 型へ変更
    change_column :users, :id, :bigint, auto_increment: true
  end

  def down
    # rollback時に bigint から int 型へ戻す
    change_column :users, :id, :int, auto_increment: true
  end
end

あとは今まで通りreferencesを使ってSocialLinkテーブルを追加すればOKです。

class CreateSocialLinks < ActiveRecord::Migration[6.1]
  def change
    create_table :social_links do |t|
      t.references  :user, null: false, foreign_key: true
      t.string      :type, null: false
      t.string      :url,  null: false

      t.timestamps
    end
  end
end

まとめ

  • Rails5.1から主キーや外部キーのデータ型がintegerからbigintに変更された
  • そのためRails5.1以前に作成したテーブルを5.1以降で参照しようとすると型不整合によるエラーが生じる

参考文献

0
0
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
0
0