2015-09-04 42 views
2

我遇到了Minitest和相關ActiveRecord模型(Rails 4.2.3)的燈具問題。Minitest:相關AR模型的燈具導致ActiveRecord :: InvalidForeignKey:PG :: ForeignKeyViolation運行測試時

這裏有兩種型號:

# vanguard_fund.rb 
class VanguardFund < ActiveRecord::Base 
    belongs_to :benchmark_fund 
    ... 
end 

# benchmark_fund.rb 
class BenchmarkFund < ActiveRecord::Base 
    has_many :vanguard_funds 
end 

漂亮的直線前進。現在,這裏的燈具:

# vanguard_funds.yml 
vf1: 
    name: Vanguard Fund 1 
    benchmark_fund: bm1 

# benchmark_funds.yml  
bm1: 
    name: Benchmark Fund 1 

現在運行任何測試時,我發現了以下錯誤:

ERROR["test_#name_returns_the_name_of_the_VanguardFund", BaseTest, 2015-06-08 13:39:28 +0000] 
test_#name_returns_the_name_of_the_VanguardFund#BaseTest (1433770768.22s) 
ActiveRecord::InvalidForeignKey:   ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: insert or update on table "vanguard_funds" violates foreign key constraint "fk_rails_994ab6fe75" 
     DETAIL: Key (benchmark_fund_id)=(479852872) is not present in table "benchmark_funds". 
     : INSERT INTO "vanguard_funds" ("name", "created_at", "updated_at", "id", "benchmark_fund_id") VALUES ('Vanguard Fund 1', '2015-09-04 16:48:23', '2015-09-04 16:48:23', 263706224, 479852872) 
      test_after_commit (0.4.1) lib/test_after_commit.rb:15:in `block in transaction_with_transactional_fixtures' 
      test_after_commit (0.4.1) lib/test_after_commit.rb:9:in `transaction_with_transactional_fixtures' 

基準基金ID(479852872),但它似乎像該記錄在創建VanguardFund時沒有在BenchmarkFunds表中找到?

有什麼建議嗎?

+0

它是否在'VanguardFund'之前加載'BenchmarkFund'? –

+0

@ muistooshort我不知道夾具加載是如何工作的,但我會這樣認爲,因爲它首先按字母順序排列。事實上,假設ActiveRecord比依靠字母順序來處理這種事情更復雜,所以我非常難以理解可能發生的事情 – sixty4bit

回答

6

我相信Rails會在加載fixture之前嘗試禁用引用完整性檢查。如果您的PostgreSQL用戶不是超級用戶,那麼這會失敗,然後夾具加載將失敗,並顯示您看到的ActiveRecord::InvalidForeignKey錯誤。

修正是讓您的PostgreSQL用戶成爲超級用戶。使用特權帳戶連接到PostgreSQL,然後發出ALTER USER ... WITH SUPERUSER命令。

在Ubuntu上,我這樣做是這樣的:

su -l postgres -c "psql -c 'alter user jenkins with superuser;'" 

jenkins在這種情況下是被失敗運行Rails的測試用戶。這爲我解決了這個問題。

有一個在edge version of the Rails testing guide(強調)一個這樣的解釋:

爲了從數據庫中刪除現有的數據,Rails的嘗試禁用參照完整性觸發器(如外鍵和檢查約束)。如果您在運行測試時遇到惱人的權限錯誤,請確保數據庫用戶有權在測試環境中禁用這些觸發器。 (在PostgreSQL中,只有超級用戶可以禁用所有觸發器。閱讀更多關於PostgreSQL權限here)。

相關問題