我在使用 Postgresql 13 的 Rails 7 應用程式中進行了此遷移:
class AddContractsDateRangeConstraint < ActiveRecord::Migration[7.0]
def up
execute "CREATE EXTENSION IF NOT EXISTS btree_gist"
execute <<~SQL
ALTER TABLE contracts
ADD CONSTRAINT date_overlap_exclude
EXCLUDE USING GIST (
employee_id WITH =,
daterange(starts_on, ends_on) WITH &&
)
SQL
end
def down
execute "ALTER TABLE contracts DROP CONSTRAINT date_overlap_exclude"
end
end
通過rails db:migrate約束執行時,會像這樣將其添加到資料庫中,并且一切正常:
app_development=# \d contracts
...
Indexes:
...
"date_overlap_exclude" EXCLUDE USING gist (employee_id WITH =, daterange(starts_on, ends_on) WITH &&)
...
從 Rails生成schema.rb的檔案如下所示:
create_table "contracts", force: :cascade do |t|
# ...
t.index "employee_id, daterange(starts_on, ends_on)", name: "date_overlap_exclude", using: :gist
# ...
end
這看起來很可疑,因為它缺少EXCLUDE我的約束的全部內容。事實上,當使用rails db:schema:load約束從生成的模式創建資料庫時,它會被破壞并生成如下:
app_development=# \d contracts
...
Indexes:
"contracts_pkey" PRIMARY KEY, btree (id)
"date_overlap_exclude" gist (employee_id, daterange(starts_on, ends_on))
當然,整個約束不再起作用。知道如何解決這個問題嗎?
uj5u.com熱心網友回復:
Rails Ruby 模式轉儲器非常適合簡單的應用程式和用例,但它實際上只能理解非常有限的 SQL 子集。正如您在這里所經歷的那樣,它不理解的資料庫模式的任何部分都只是在翻譯中丟失了。
一旦您需要使用函式、約束、物化視圖或任何其他特定于資料庫的功能,您就需要使用更高保真度的 SQL 模式轉儲,因為它只是使用資料庫自??己的轉儲工具將模式輸出為 SQL . 雖然您正在失去 schema.rb 的簡單性和與資料庫無關的特性,但隨著應用程式復雜性的增加,這是不可避免的變化。
您可以在配置中使用簡單的一行來切換架構格式:
module YourApp
class Application < Rails::Application
# Add this line:
config.active_record.schema_format = :sql
end
end
當你運行rails db:schema:dump它時,它現在會輸出一個structure.sql檔案。此時,您應該洗掉您的schema.rb并檢查structure.sql版本控制。
看:
- 在 Ruby on Rails 應用程式中使用 structure.sql 的優缺點
- Rails 指南:模式轉儲和你
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/531222.html
