2015-09-04 22 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)。

相关问题