😀
Railsでrename_columnをするとインデックス名は自動的に変更されるのか検証してみた
はじめに
Railsアプリ開発では、モデルのカラム名を後から変更する場面がたびたびあります。
今回は以下のテーブルのリネームを行った際に、インデックス名も自動的に変更されるのかを検証してみました。
rename_column :books, :title, :title_ja
結論から言うと、インデックス名は自動的に変更されます。
この記事では、その検証方法や内部の挙動について解説します。
検証環境
- Ruby 3.3.4
- Rails 8.0.1
- SQLite3 3.45.3
モデル作成:
rails g model Book title:string
インデックスを追加:
class CreateBooks < ActiveRecord::Migration[7.1]
def change
create_table :books do |t|
t.string :title
t.timestamps
end
# 以下を手動で追記
add_index :books, :title, unique: true
end
end
マイグレーションを実行します。
rails db:migrate
これにより、以下のschema.rbが得られます。
ActiveRecord::Schema[8.0].define(version: 2025_XX_XX_XXXXXX) do
create_table "books", force: :cascade do |t|
t.string "title", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["title"], name: "index_books_on_title", unique: true
end
end
検証: カラム名を変更してみる
以下のマイグレーションでカラム名をtitle
からtitle_ja
へ変更します。
rails g migration RenameTitleToBooks
生成されたマイグレーションファイルを編集:
class RenameTitleToBooks < ActiveRecord::Migration[7.1]
def change
# 以下を手動で追記
rename_column :books, :title, :title_ja
end
end
実行します。
rails db:migrate
結果
マイグレーション後のschema.rb
を確認すると、インデックス名がindex_books_on_title
からindex_books_on_title_ja
に変更されていました。
ActiveRecord::Schema[8.0].define(version: 2025_XX_XX_XXXXXX) do
create_table "books", force: :cascade do |t|
t.string "title_ja", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["title_ja"], name: "index_books_on_title_ja", unique: true
end
end
rename_columnの内部実装をのぞいてみる
Rails内部では、rename_column
は抽象メソッドとして定義されています。
def rename_column(table_name, column_name, new_column_name)
raise NotImplementedError, "rename_column is not implemented"
end
実際の処理は各データベースアダプターで行われます。
例えばSQLiteの場合は、以下のように内部でカラム名のみの変更(alter_table)と、カラムに紐づくインデックスの名前変更(rename_column_indexes)も行なっています。
def rename_column(table_name, column_name, new_column_name) # :nodoc:
column = column_for(table_name, column_name)
alter_table(table_name, rename: { column.name => new_column_name.to_s })
rename_column_indexes(table_name, column.name, new_column_name)
end
注意: 明示的に指定したインデックス名は自動変更されない
注意点として、もし自分で明示的に名前を指定した場合(name
オプション)は、rename時にインデックス名は自動で変更されません。
add_index :books, :title, name: "custom_index_books_on_title"
この場合は手動で対応する必要があります。
まとめ
検証の結果、Railsのrename_column
では、通常の命名規則に従ったインデックス名は自動的に変更されることがわかりました。
少しでも参考になれば嬉しいです。
Discussion