モデル名を変更したい場合、該当デーブルだけを変更する場合は特に何も考慮に入れる必要はないが、該当テーブルを参照する子モデルがあった場合、子モデルの外部キーも変更する必要があります。
まだ未公開のプロジェクトの場合は、既存のmigrationファイルを書き換えてrails db:migrate:reset
をすれば良いですが、既にデータが存在しているプロジェクトではそうもいきません。
モデルの準備
まずはモデルを準備します。今回はUser has_many Tasksの関係であるUserモデルとTaskモデルを用意を用意します。
モデルの中身をわかりやすくするため、今回は外部キー以外のカラムは書かないことにします。
rails g model User
rails g model Task user:references
上記のコマンドで下記2つのマイグレーションファイルが作成されます。
class CreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
t.timestamps
end
end
end
class CreateTasks < ActiveRecord::Migration[6.0]
def change
create_table :tasks do |t|
t.references :user, null: false, foreign_key: true
t.timestamps
end
end
end
rails db:migrate
でschema.rbが更新されます。
ActiveRecord::Schema.define(version: 2020_10_04_121556) do
create_table "tasks", force: :cascade do |t|
t.integer "user_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["user_id"], name: "index_tasks_on_user_id"
end
create_table "users", force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
add_foreign_key "tasks", "users"
end
railsではreference型を与えると勝手にindexが貼られます。
index: true
としなくてもt.index ["user_id"], name: "index_tasks_on_user_id"
が記述されていますね。
また、foreign_key: true
が付与されていたため、add_foreign_key "tasks", "users"
が記述されていますね。
以上、Userモデルとそれに紐づくTaskモデルが作成されました。
モデル名を変更する
それでは、UserモデルをAdminUserに変更しましょう。
まずは普通にモデル名を変更するmigrationファイルを作成し、migrateします。
rails g migration RenameUserToAdminUser
で下記ファイルを作成し、rails db:migrate
class RenameUserToAdminUser < ActiveRecord::Migration[6.0]
def change
rename_table :users, :admin_users
end
end
それではschema.rbを確認しましょう。ご覧の通り、
①userはadmin_userに名称変更されています。
しかし、
②taskモデルの外部キーはuser_idのままで変名されていません。(当たり前といえば当たり前)
そして、
③外部キー制約部分はuser_idというカラム名のまま、admin_userに紐付けされています。
ActiveRecord::Schema.define(version: 2020_10_04_123215) do
create_table "admin_users", force: :cascade do |t| # ←①
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "tasks", force: :cascade do |t|
t.integer "user_id", null: false # ←②
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["user_id"], name: "index_tasks_on_user_id"
end
add_foreign_key "tasks", "admin_users", column: "user_id" # ←③
end
このschemaを確認すれば、外部キー制約のついたカラム名を変更すれば一連の修正が完成しそうですね!
外部キーカラム名を変更する
それでは、カラム名変更をするmigrationファイルを作成していきます。
rails g migration RenameUserIdToAdminUserId
class RenameUserIdToAdminUserId < ActiveRecord::Migration[6.0]
def change
rename_column :tasks, :user_id, :admin_user_id
end
end
rails db:migrate
カラム名変更が反映されましたね。
④Taskモデルのuser_idがadmin_user_idになり、
⑤外部キーのcolumn名指定がなくなりました。
ActiveRecord::Schema.define(version: 2020_10_04_125441) do
create_table "admin_users", force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "tasks", force: :cascade do |t|
t.integer "admin_user_id", null: false # ←④
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["admin_user_id"], name: "index_tasks_on_admin_user_id"
end
add_foreign_key "tasks", "admin_users" # ←⑤
end
まとめ
外部キー制約が貼られたモデル名を変更するには、
- モデル名を変更する
- 該当モデルへの外部キー名を変更する
これだけでいけちゃいました。案外簡単でしたね。
特にモデル名変更するだけで外部キーの向き先も変えてくれるのはさすがRailsだな〜って感じでした。