Rails 7 adds support for `if_exists/if_not_exists` on `remove_foreign_key/add_fo...
source link: https://blog.saeloun.com/2021/07/14/rails-7-if_exists-if_not_exists-on-remove-add-foreign-key
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Rails 6.1 added support for if_exists/if_not_exists on remove/add column and extended it further to support if_not_exists on add_index and if_exists on remove_index.
To maintain the same behavior across add/remove constraints of databases, Rails 7 added support for if_exists/if_not_exists on remove_foreign_key/add_foreign_key.
Before Rails 7
Add foreign key
Let’s say we have an e-commerce application with Order
and User
models.
An order belongs to a user,
and we want to add a user_id
foreign key constraint on the orders
table.
We would add a migration as shown below:
class AddUserReferenceToOrder < ActiveRecord::Migration[6.0]
def change
add_foreign_key :orders, :users
end
end
But if the orders
table already contains foreign_key constraint on the user,
the above DB migration will raise an error.
rails db:migrate
== 20210714080612 AddUserReferenceToOrder: migrating ================
-- add_foreign_key(:orders, :users)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::DuplicateObject: ERROR: constraint "fk_rails_11f1189a77" for relation "orders" already exists
Remove foreign key
Similarly,
if we try to remove a foreign_key constraint that never existed on
orders
table the migration would also raise an error.
class RemoveProductReferenceFromOrder < ActiveRecord::Migration[6.0]
def change
remove_foreign_key :orders, :products
end
end
rails db:migrate
== 20210714080712 RemoveProductReferenceFromOrder: migrating ================
-- remove_foreign_key(:orders, :products)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
Table 'orders' has no foreign key for products
In Rails 7
To avoid above issues and to keep things consistent,
Rails team added support to pass if_exists/if_not_exists
options
to remove_foreign_key/add_foreign_key
.
With this change, the below migrations run successfully without raising any error.
Add foreign key
class AddUserReferenceToOrder < ActiveRecord::Migration[6.0]
def change
add_foreign_key :orders, :users, if_not_exists: true
end
end
rails db:migrate
== 20210714080612 AddUserReferenceToOrder: migrating ================
-- add_foreign_key(:orders, :users, {:if_not_exists=>true})
-> 0.0151s
== 20210714080612 AddUserReferenceToOrder: migrated (0.0153s) ==================
Remove foreign key
class RemoveProductReferenceFromOrder < ActiveRecord::Migration[6.0]
def change
remove_foreign_key :orders, :products, if_exists: true
end
end
rails db:migrate
== 20210714080712 RemoveProductReferenceFromOrder: migrating ================
-- remove_foreign_key(:orders, :products, {if_exists: true})
-> 0.0118s
== 20210714080712 RemoveProductReferenceFromOrder: migrated (0.0118s) ================
Check out this pull request for more details.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK