経緯とか
Railsに以下のようなモデルを追加しようとしたら、 index name ... too long
というエラーになったので、対処法を覚え書くことにした。
20180925044739_create_payment_method_restrictions.rb
class CreatePaymentMethodRestrictions < ActiveRecord::Migration
def change
create_table :payment_method_restrictions do |t|
t.references :product, null: false
t.integer :payment_method_cd, null: false
t.timestamps null: false
end
add_index :payment_method_restrictions, [:product_id, :payment_method_cd], unique: true
end
end
環境
Ruby 2.4.2
Rails 4.2.10
MySQL Sandbox 5.6.23
現象
rake db:migrate
を実行したら Index name が長すぎると怒られた。
rake aborted!
StandardError: An error has occurred, all later migrations canceled:
Index name 'index_payment_method_restrictions_on_product_id_and_payment_method_cd' on table 'payment_method_restrictions' is too long; the limit is 64 characters
対処
以下のサイトを参考に Index name を任意の名前に変えることで文字数制限を回避した。
http://gutch.hatenablog.com/entry/20120222/1329890161
# before
add_index :payment_method_restrictions, [:project_id, :payment_method_cd], unique: true
# after
add_index :payment_method_restrictions, [:project_id, :payment_method_cd], unique: true, name: 'payment_method_restrictions_index'
Mysql2::Error: Table 'table_name' already exists
とさらに怒られた
最初にrake db:migrate
を実行したときにテーブルが作成されてしまったようで、rake db:rollback
してもうまく元に戻らなかった。
以下のサイトを参考にして手動でテーブルを削除してから再度rake db:migrate
を実行したら治りました。
https://bokunonikki.net/post/2018/0214_rails_mysql_error/
$ rails db
# パスワードを求められるのでMySQLユーザーのパスワードを入力する
mysql> show tables like 'payment_%';
+--------------------------------------------+
| Tables_in_readyfor_development (payment_%) |
+--------------------------------------------+
| payment_method_restrictions |
+--------------------------------------------+
1 row in set (0.00 sec)
mysql> drop table payment_method_restrictions;
Query OK, 0 rows affected (0.01 sec)
mysql> show tables like 'payment_%';
Empty set (0.00 sec)
おまけ
文字数制限を回避するため、restriction -> limit に変更することも考えたが、ちょっと意味合いが違うと思い、今回の方法を見つけました。