5
1

More than 1 year has passed since last update.

Rails indexのおかげでdb:migrateができなかった話

Last updated at Posted at 2022-10-07

はじめに

テーブル作成の際に

rails db:migrate

を実行したのにも関わらず、次のようなエラーでテーブルが作成されないという事象がありました。

ArgumentError: Index name 'index_long_long_long_long_long_long_long_tests_on_long_long_long_user_id' on table
 'long_long_long_long_long_long_long_tests' is too long; the limit is 64 characters

index名が長すぎるというエラーでした。
しかし、異なる部分でも時間を溶かしてしまったので備忘録として残したいと思います。
いつものようにおかしな点や誤っている点はご指摘お待ちしています!

環境

ruby 2.7,1
rails 6.0.5

indexとは

今回のテーブル設計では、「そもそもindexってなんっちゃか?」というところからのスタートでした。
こちらの記事がわかりやすかったです。

indexとは

特定のカラムからデータを取得する際に、テーブルの中の特定のカラムのデータを複製し検索が行いやすいようにしたものです。

  • メリット:データの読み込み・取得が早くなる。
  • デメリット:書き込みの速度が倍かかる。

indexは

ある程度多くのデータを格納するテーブルの、格納される値がそれぞれ異なるようなカラムの中で、検索がよく行われるカラム

に使用するべきとのことです。なるほど!

前提

今回は長いテーブル名をつけたときにこのindexを貼ったことが原因でエラーになりました。
順を追っていきます。

long_long_long_long_long_long_long_testモデルを作ります。
rails g model long_long_long_long_long_long_long_test

次のように様々なファイルが作成されます。

Running via Spring preloader in process 7663
      invoke  active_record
      create    db/migrate/20221006024900_create_long_long_long_long_long_long_long_tests.rb
      create    app/models/long_long_long_long_long_long_long_test.rb
      invoke    rspec
      create    spec/models/long_long_long_long_long_long_long_test_spec.rb
マイグレーションファイルを記述します。
class CreateLongLongLongLongLongLongLongTests < ActiveRecord::Migration[5.1]
  def change
    create_table :long_long_long_long_long_long_long_tests do |t|
      t.string :long_long_long_name, null: false
      t.references :long_long_long_user, foreign_key: true
      t.timestamps
    end
  add_index :long_long_long_long_long_long_long_tests, :long_long_long_name
  end
end

add_indexでindexを貼り、rails db:migrateを実行しました。

課題

index名が長い!

マイグレーションを実行すると、ArgumentErrorが出ました。

ArgumentError: Index name 'index_long_long_long_long_long_long_long_tests_on_long_long_long_user_id' on table
 'long_long_long_long_long_long_long_tests' is too long; the limit is 64 characters

どうやらindex名が長すぎるようです。

解決

この記事によるとindexは次の3つのときに追加されます。

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

つまり今回はt.referencesでindexが貼られていることになります。
ここのindex名が長すぎると怒られていたわけでした。
t.referencesの場合はindexオプションで名前を指定することができます。

class CreateLongLongLongLongLongLongLongTests < ActiveRecord::Migration[5.1]
  def change
    create_table :long_long_long_long_long_long_long_tests do |t|
      t.string :long_long_long_name, null: false
      t.references :long_long_long_user, foreign_key: true, index: { name: 'index_name' } # ここを追加
      t.timestamps
    end
  add_index :long_long_long_long_long_long_long_tests, :long_long_long_name
  end
end

これで一件落着!rails db:migrateを実行します。

そのテーブルはすでにあるよ!

ArgumentError: Index name 'index_long_long_long_long_long_long_long_tests_on_user_id' on table
 'long_long_long_long_long_long_long_tests' already exists

なんだと・・・すでにテーブルがあるだと・・・
確認してみます。
次のコマンドを実行します。

rails db

パスワードを求められますので入力します。

MySQL [ai_brid_development]> 

mysqlにログインできました。テーブルを見てみます。

MySQL [ai_brid_development]>  SHOW TABLES;

image.png
ありました!
削除します!

MySQL [ai_brid_development]> DROP TABLE long_long_long_long_long_long_long_tests

これで今度こそできるはずです!
SQLからexitで抜け、rails db:migrateを実行します。

index名が長い再び!

ArgumentError: Index name 'index_long_long_long_long_long_long_long_tests_on_long_long_long_name' on table
 'long_long_long_long_long_long_long_tests' is too long; the limit is 64 characters

おやまたエラーになりました。
今度はlong_long_long_nameと出ています!
違う箇所でエラー発生??

・・・そうか!
add_indexについても当然indexが貼られるわけなので、名前が長すぎると言われるのは当然ですね!
index名が長すぎるのであれば、add_indexについてはname属性でindex名を指定できます。

class CreateLongLongLongLongLongLongLongTests < ActiveRecord::Migration[5.1]
  def change
    create_table :long_long_long_long_long_long_long_tests do |t|
      t.string :long_long_long_name, null: false
      t.references :long_long_long_user, foreign_key: true, index: { name: 'index_name' }
      t.timestamps
    end
  add_index :long_long_long_long_long_long_long_tests, :long_long_long_name, name: 'index_name2' # ここを追加
  end
end

これで解決です!

おわりに

エンジニアになって6か月。
テーブル設計を任せてもらうようになりましたが、本当に実力不足を痛感しています。
今回のindexもよくわかっていませんでした。
今でもわかっているのかは疑問ですが、日々積み重ねていきたいと思います。

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