【问题标题】:Minitest: fixtures for associated AR models results in ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation when tests are runMinitest:相关 AR 模型的夹具在运行测试时导致 ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation
【发布时间】:2015-09-04 17:00:24
【问题描述】:

我在使用 Minitest 和相关 ActiveRecord 模型(Rails.4.2.3)的固定装置时遇到了问题。

这是两个模型:

# 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 表中找不到该记录??

有什么建议吗?

【问题讨论】:

  • 是否在VanguardFunds 之前加载BenchmarkFunds?
  • @muistooshort 我不知道夹具加载是如何工作的,但我认为是这样,因为它按字母顺序排在第一位。事实上,假设 ActiveRecord 比依赖字母顺序来处理这类事情更复杂,所以我对可能发生的事情感到很困惑

标签: ruby-on-rails ruby postgresql fixtures minitest


【解决方案1】:

我相信 Rails 会在加载固定装置之前尝试禁用引用完整性检查。如果您的 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)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-15
    • 2020-10-19
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 2015-10-25
    相关资源
    最近更新 更多