If you want to change the model name, you don't need to take anything into consideration if you want to change only the corresponding table, but if you have a child model that references the corresponding table, you also need to change the foreign key of the child model.
For a project that hasn't been published yet, you can rewrite the existing migration file and do rails db: migrate: reset
, but not for a project that already has data.
First, prepare the model. This time, we will prepare the User model and Task model, which are related to User has_many Tasks. To make the contents of the model easier to understand, I will not write any columns other than foreign keys this time.
rails g model User
rails g model Task user:references
The above command will create the following two migration files.
db/migration/20201004121521_create_users.rb
class CreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
t.timestamps
end
end
end
db/migration/20201004121556_create_tasks.rb
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
updates schema.rb.
db/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
In rails, if you give a reference type, the index will be pasted without permission.
Even if you don't set ʻindex: true,
t.index ["user_id"], name: "index_tasks_on_user_id" is described. Also, since
foreign_key: true was given, ʻadd_foreign_key" tasks "," users "
are described.
As mentioned above, the User model and the Task model associated with it have been created.
Now let's change the User model to AdminUser. First, create a migration file that changes the model name normally, and migrate it.
Create the following file with rails g migration RenameUserToAdminUser
and rails db: migrate
db/migration/20201004123215_rename_user_to_admin_user.rb
class RenameUserToAdminUser < ActiveRecord::Migration[6.0]
def change
rename_table :users, :admin_users
end
end
Now let's check schema.rb. As you can see, ① user has been renamed to admin_user.
But, (2) The foreign key of the task model remains user_id and has not been renamed. (Speaking of course, of course)
And (3) The foreign key constraint part is linked to admin_user with the column name user_id.
db/schema.rb
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
If you check this schema, it seems that a series of corrections will be completed if you change the column name with the foreign key constraint!
Now, let's create a migration file that changes the column name.
rails g migration RenameUserIdToAdminUserId
db/migration/20201004125441_rename_user_id_to_admin_user_id.rb
class RenameUserIdToAdminUserId < ActiveRecord::Migration[6.0]
def change
rename_column :tasks, :user_id, :admin_user_id
end
end
rails db:migrate
The column name change has been reflected. ④ The user_id of the Task model becomes admin_user_id, (5) The column name of the foreign key is no longer specified.
db/schema.rb
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
To change the model name with a foreign key constraint
This was all I could do. It was unexpectedly easy. In particular, it was Rails that changed the direction of foreign keys just by changing the model name.
Recommended Posts