🐙
【Rails】rename_tableするときはrename_columnも必要な場合がある
結論
rename_tableするときは外部キーの関連でrename_columnも必要な場合がある。
詳細
例えば、少々強引だけどUserモデルを定義すべきところをUserrとタイポして作ったとき。Userr has_many Bookという関連があるとする。
この場合、当然Bookモデルにはuserr_idという外部キーを保存するカラムがある。
ActiveRecord::Schema[7.1].define(version: 2024_06_25_103655) do
create_table "books", force: :cascade do |t|
t.string "title", null: false
t.integer "userr_id", null: false #外部キーもタイポされてる
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["userr_id"], name: "index_books_on_userr_id"
end
create_table "userrs", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_foreign_key "books", "userrs"
end
このままではまずいので、rename_tableメソッドを使い、userrs->usersへテーブル名を変更する。
class RenameTable < ActiveRecord::Migration[7.1]
def change
rename_table :userrs, :users
end
end
実行後、テーブル名はusersに変更されたが、Book#userr_id外部キーは修正されていない。
ActiveRecord::Schema[7.1].define(version: 2024_06_25_103838) do
create_table "books", force: :cascade do |t|
t.string "title", null: false
t.integer "userr_id", null: false # 外部キーはまだuserrのまま
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["userr_id"], name: "index_books_on_userr_id" # indexもまだuserrのまま
end
create_table "users", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_foreign_key "books", "users", column: "userr_id"
end
よって、rename_columnメソッドも実行する。こうすることで、カラム名とインデックス名が修正される。
class RenameTable < ActiveRecord::Migration[7.1]
def change
rename_table :userrs, :users
rename_column :books, :userr_id, :user_id #userr_idからuser_idへリネーム
end
end
スキーマを見ると、
-
Book#userr_id->Book#user_id -
"index_books_on_userr_id"->"index_books_on_user_id"
に変更されているのがわかる。
ActiveRecord::Schema[7.1].define(version: 2024_06_25_103838) do
create_table "books", force: :cascade do |t|
t.string "title", null: false
t.integer "user_id", null: false #リネームされてる
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_books_on_user_id" #こちらも修正されている
end
create_table "users", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_foreign_key "books", "users"
end
インデックス名を変更するのにrename_indexというメソッドもあるが、これはインデックス名のみを変える。だから今回の例のように、カラム名の変更も必要な場合はrename_columnを使うとよい。
ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter
Discussion