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

Subscribe to my newsletter and never miss my upcoming articles

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


No Comments Yet