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. 【ツール開発】ポケモンの種族値と実数値を調べるツール – 1
  2. 【MySQL】mysqlで新しくユーザーを追加する
  3. 【Blender】起動時に強制終了してしまう問題
  4. 【Rails】findメソッドで連想配列から指定した値を検索する
  5. 【Blender】アニメーションでポーズを左右反転してコピペしたい時

関連記事

 
  1. 【Rails】オブジェクトの中身をログに出力する

    Ruby on Rails

    【Rails】オブジェクトの中身をログに出力する

    オブジェクトの中身をデバッグしたりする時に便利出力結果をみやすい形に…

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

    Ruby on Rails

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

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

  3. Ruby on Rails

    【Rails】レコードが保存済みか確認するpresisted?メソッド

    レコードが保存されているかどうかでUIの表示を切り替えたり、保存されて…

  4. Ruby on Rails

    【Rails】RSpecのお作法メモ

    RSpecを書く機会が増えてきたので、記法の備忘録として記事にします…

  5. Ruby on Rails

    【Rails】development? production? 開発環境ごとに処理を切り分けたい時

    Railsで、開発環境ごとに処理を切り替えたい時の方法を紹介します。ま…

  6. Ruby on Rails

    【Rails】selectメソッドで特定の条件を満たす要素を取得する

    selectは、配列に対してブロック内の条件を評価し、真になって要素を…

カレンダー

2021年9月
 12345
6789101112
13141516171819
20212223242526
27282930  

最近の記事

  1. Ruby on Rails

    【Rails】selectメソッドで特定の条件を満たす要素を取得する
  2. Ruby on Rails

    【Rails】modelを作成する
  3. WordPress

    【WPテーマ自作】ローカル環境でWP開発ができる「Local」の導入
  4. Ruby on Rails

    【Rails】railsでIndex name ‘xxx’…
  5. WordPress

    【WPテーマ自作】UnderScoresの導入
PAGE TOP