Ruby on Rails

【Rails】railsでIndex name ‘xxx’ on table ‘xxx’ is too long; の対処法

rake db:migrate でテーブルを作成した時、index名が長すぎると下記のようなエラーが出ます。

Index name 'index_name' on table 'table_name' is too long; the limit is 64 characters

railsでindexが追加されるのは主にこの3つです

  1. t.references で関連づけた場合
  2. index: true オプションで関連づけた場合
  3. add_index で関連づけた場合

それぞれ対処法が異なるので、今回はこちらを紹介したいと思います。

結論

t.references で関連づけたindex名を変更する場合

t.references :table_name, index: { name: 'index_name' }

index: true オプションで関連づけたindex名を変更する場合

t.integer :column_name, index: { name: 'index_name' }

add_indexで関連づけたindex名を変更する場合

add_index :table_name, :column_name, name: 'index_name'

目次

  1. 結論
  2. 環境
  3. migrationを実行したらエラーが出た
  4. Railsでindexが貼られるパターン
  5. t.references で関連づけた場合
    1. indexオプションで名前を指定する
  6. index: true オプションで関連づけた場合
    1. name属性でindex名を指定する
  7. add_index で関連づけた場合
    1. name属性でindex名を指定する
  8. まとめ

環境

作業環境

OS: MacOS
メモリ: 32GB

Dependents
Rails6
Ruby 2.6
CentOS7 on Vagrant
Mysql 5.7

migrationを実行したらエラーが出た

Railsのmigrationについては、公式ドキュメントに詳細が載っていますので
そちらを見てみてください。

Railsドキュメント – マイグレーションとは

既存のアプリケーションに、新しいテーブルを追加するために
migrationファイルを作成しました。
(内容は適当です)

# migrationファイル

class CreateMigrationErrorTables < ActiveRecord::Migration[6.1]
  def change
    create_table :migration_index_name_errors do |t|
      t.integer :error_num, null: false
      t.string :error_string

      t.timestamps
    end

    create_table :migration_index_name_error_items do |t|
      t.references :item, null: false

      t.integer :display_order, null: false

      t.timestamps
    end
  end
end

こちらでmigrationを実行した所、このようなエラーが発生しました。
ログの全文はこんな感じです。

# log

[vagrant@sample app]$ bundle exec rake db:migrate

== 20210426060841 CreateMigrationErrorTables: migrating ======================
-- create_table(:migration_index_name_errors)
   -> 0.0128s
-- create_table(:migration_index_name_error_items)
rake aborted!
StandardError: An error has occurred, all later migrations canceled:

Index name 'index_migration_index_name_error_items_on_migration_index_name_error_id' on table 'migration_index_name_error_items' is too long; the limit is 64 characters
/home/vagrant/app/db/migrate/20210426060841_create_migration_error_tables.rb:10:in `change'
/home/vagrant/.rbenv/versions/2.7.2/bin/bundle:23:in `load'
/home/vagrant/.rbenv/versions/2.7.2/bin/bundle:23:in `<main>'

Caused by:
ArgumentError: Index name 'index_migration_index_name_error_items_on_migration_index_name_error_id' on table 'migration_index_name_error_items' is too long; the limit is 64 characters
/home/vagrant/app/db/migrate/20210426060841_create_migration_error_tables.rb:10:in `change'
/home/vagrant/.rbenv/versions/2.7.2/bin/bundle:23:in `load'
/home/vagrant/.rbenv/versions/2.7.2/bin/bundle:23:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)

エラー部分のみ抜粋するとこんな感じです。

ArgumentError: Index name ‘index_migration_index_name_error_items_on_migration_index_name_error_id’ on table ‘migration_index_name_error_items’ is too long; the limit is 64 characters

indexの文字数上限は64文字なので長すぎるよ、と言われています。
これがindex名ですね。

index_migration_index_name_error_items_on_migration_index_name_error_id

このエラーの対処法を紹介していきたいと思います。

Railsでindexが貼られるパターン

上のmigrationファイルでは、t.references でテーブルを関連づけてindexを貼りました。
Railsでは他にもテーブルにindexを貼る方法があり、他の方法でも同様のエラーが発生する事があるので、そのパターンも見ていきたいと思います。

  1. t.references で関連づけた場合
  2. index: true オプションで関連づけた場合
  3. add_index で関連づけた場合

t.references で関連づけた場合

referencesについても、公式ドキュメントに詳細な記述がありますので興味のある方はそちらも参照してください。

Railsドキュメント – リファレンスを生成

migration実行時、t.referencesでテーブル同士の関連付けを行っている場合にはRails側で自動的にindexが貼られます。
上で紹介したmigrationファイルのパターンですね。

# migrationファイル

create_table :migration_index_name_error_items do |t|
  # t.references :table_name で関連付けすると自動でindexを貼ってくれる
  t.references :item, null: false
~~ 中略 ~~
  t.timestamps
end

このような場合に、index_nameの長さでエラーが発生した場合には
indexオプションを追加する事で、index名を指定することで回避できます。

indexオプションで名前を指定する

indexというオプションがmigrationでは使用できますので
こちらを使って、index名を指定します。

書き方は、index の値にハッシュでnameを指定してあげます。

# migrationファイル

create_table :migration_index_name_error_items do |t|
  # index { name: 'index_name' }でindex名を指定できる
  t.references :item, null: false, index: { name: 'migration_index_name_error_items_index' }
~~ 中略 ~~
  t.timestamps
end

これで、migrationを実行することで
index名の長さでエラーにならずに、migrationが通るようになります。

index: true オプションで関連づけた場合

次は、indexオプションで通常のカラムにindexを貼った場合です。
公式ドキュメント ではテーブル定義変更(change_table)のオプションとしてindexが載っていますが、テーブル作成(create_table)でも問題なく使えます。

Railsドキュメント – テーブル定義を変更

# migrationファイル

create_table :migration_index_name_error_items do |t|
  # index: true でintやstringのカラムに対してもindexを貼れる
  t.integer :item_num, index: true
~~ 中略 ~~
  t.timestamps
end

t.integer :item_num, index: true のように、通常のカラムに対しても
Railsではオプションでindexを付与することができます。

name属性でindex名を指定する

referencesで紹介したのと同様に、indexオプションにname属性を追記してあげることで、index名を指定することができます。

# migrationファイル

create_table :migration_index_name_error_items do |t|
  # index { name: 'index_name' }でindex名を指定できる
  t.integer :item_num, index: { name: 'migration_index_name_error_items_index' }
~~ 中略 ~~
  t.timestamps
end

これで、migrationを実行することで
index名の長さでエラーにならずに、migrationが通るようになります。

add_index で関連づけた場合

migrationファイルには、もう一つindexを追加する方法があります。
それが、add_indexを使う方法です。

# migrationファイル

create_table :migration_index_name_error_items do |t|
  t.integer :item_num
~~ 中略 ~~
  t.timestamps
end

# add_index :tabel_name, :column_name でindexを貼れる
add_index :migration_index_name_error_items, :item_num

add_indexは、一度作成したテーブルに後からindexを貼ることができます。
この方法で追加したindexが、文字数制限エラーになった場合
今まで紹介した方法と同様に、name属性を追加してindex名を指定することができます。

name属性でindex名を指定する

add_index :tabel_name, :column_name, name: ‘index_name’ で、index名を指定することができます。

# migrationファイル

create_table :migration_index_name_error_items do |t|
  t.integer :item_num
~~ 中略 ~~
  t.timestamps
end

# name属性を追加することで、index名を指定できる
add_index :migration_index_name_error_items, :item_num, name: 'migration_index_name_error_item_index'

nameは文字列で指定する必要があるので、“(シングルクォーテーション)で囲ってください。
これで、migrationを実行することで
index名の長さでエラーにならずに、migrationが通るようになります。

まとめ

今回は、index名の長さでエラーが発生した場合の対処法を3パターンご紹介しました。

t.references で関連づけたindex名を変更する場合

t.references :table_name, index: { name: 'index_name' }

index: true オプションで関連づけたindex名を変更する場合

t.integer :column_name, index: { name: 'index_name' }

add_indexで関連づけたindex名を変更する場合

add_index :table_name, :column_name, name: 'index_name'

どれもやっていることはほぼ同じで
referencesでもadd_indexでも、「indexオプションでname指定できるよ」ということを知ってもらえればと思います。

ピックアップ記事

  1. 【UE4】用語備忘録メモ
  2. 【Rails】selectメソッドで特定の条件を満たす要素を取得する
  3. 【WPテーマ自作】UnderScoresの導入
  4. 【Blender】アニメーションでポーズを左右反転してコピペしたい時
  5. 【Blender】複数バージョンを簡単に管理できる、BlenderLaunche…

関連記事

 
  1. Ruby on Rails

    【Rails】ActiveStorageで添付ファイルを削除したいときは、purgeを使う

    動作確認するために、active_storageでアップロードした画…

  2. Ruby on Rails

    【Rails】文字列からHTMLタグを取り除く方法

    Railsで、HTMLタグを取り除いて文字列を出力したい時があります。…

  3. Ruby on Rails

    【Rails】modelを作成する

    結論rails generateコマンドを使いましょ…

  4. Ruby on Rails

    【Rails】migrationでカラムを追加・削除したい

    migrationファイルでよく使う記述。テーブルにカラムを追加・削…

  5. railsをproductionモードで実行する

    Ruby on Rails

    【Rails】railsをproductionモードで実行する

    結論--environmentオプションを使用します。…

カレンダー

2025年1月
 12345
6789101112
13141516171819
20212223242526
2728293031  

最近の記事

  1. Ruby on Rails

    【Rails】railsでIndex name ‘xxx’…
  2. Blender

    起動時の設定をカスタムする【Blender】
  3. Blender

    【UE4】用語備忘録メモ
  4. Blender

    【Blender】レンダリング結果を新規ウィンドウで開かないようにする
  5. Blenderの複数バージョンを簡単に管理できるBlenderLauncherの使い方

    Blender

    【Blender】複数バージョンを簡単に管理できる、BlenderLaunche…
PAGE TOP