😀

Railsでrename_columnをするとインデックス名は自動的に変更されるのか検証してみた

2025/03/09に公開

はじめに

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