Vu Minh Tien
Technical / Language / Lifestyle

Technical / Language / Lifestyle

Rails 7 - Bổ sung option "if_exists/if_not_exists" khi thêm/xóa foreign_key trong migration ⛑️⛑️⛑️

Rails 7 - Bổ sung option "if_exists/if_not_exists" khi thêm/xóa foreign_key trong migration ⛑️⛑️⛑️

Vu Minh Tien's photo
Vu Minh Tien
·Jul 27, 2021·

2 min read

Subscribe to my newsletter and never miss my upcoming articles

Play this article

Hello mọi người, lại là Tiến đây. Hôm nay mình sẽ chia sẻ mọi người chút thay đổi ở version Rails 7 mới nhất nhé.

Rails 6.1 đã thêm hỗ trợ cho if_exists/if_not_exists trên loại để add/remove column và mở rộng nó hơn nữa để hỗ trợ if_not_exists trên add_indexif_exists trên remove_index.

Để duy trì cùng một hành vi trên các rằng buộc add/remove của database, Rails 7 đã bổ sung hỗ trợ if_exists/if_not_exists trên remove_foreign_key/add_foreign_key trong migration.

Before Rails 7 ⛹️⛹️⛹️

Add foreign key 🤔

Giả sử chúng ta có 2 bảng OrderUser , Order sẽ thuộc về(belongs_to) một User. Chúng ta sẽ thêm user_id làm foreign_key vào bảng Order. Thể hiện migration sẽ như sau:

class AddUserReferenceToOrder < ActiveRecord::Migration[6.0]
  def change
    add_foreign_key :orders, :users
  end
end

Nhưng nếu bảng Order đã có khóa ngoại user_id đối với User, migration sẽ raise lỗi ❌❌❌

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 🤔

Tương tự, nếu chúng ta cố gắng loại bỏ foreign_key user_id trên bảng Order nhưng nó không tồn tại ở bảng Order thì cũng sẽ raise lỗi ❌❌❌

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 🤾🤾🤾

Để tránh các vấn đề trên và giữ mọi thứ được nhất quán. Team phát triển Rails đã bổ sung thêm option if_exists/if_not_exists để remove_foreign_key/add_foreign_key . Với sự thay đổi này, quá trình chạy migration bên dưới sẽ thành công và không gây ra bất kỳ lỗi nào

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) ================

mlem mlem....Hí hí 🤤🤤

Bạn có thể xem chi tiết thay đổi lại tại pull request của source Rails trên Github


Did you find this article valuable?

Support Vu Minh Tien by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors
 
Share this