【发布时间】:2018-11-03 01:02:57
【问题描述】:
我有一个使用 rspec/fixtures 的 Rails 5.1 项目,我无法让fixture 加载与 belongs_to/has_one/has_many 关联的对象:我请求该fixture 的对象返回时,它的_id 列充满了看似随机的编号,ActiveRecord 将关联视为nil。这发生在具有许多关联的大型类以及只有少数字段的小型数据类上。
如果在我的测试代码中,我将这些关联分配给普通的 Ruby 代码,则对象表现正常并且我的测试通过。但是,当通过夹具加载相同的数据时,关联的记录不可用,并且需要跨越关联的数据的测试会失败。
例如,这里有两个受影响的类:
#app/models/location.rb
class Location < ActiveRecord::Base
has_many :orders
has_many :end_user
belongs_to :retailer
belongs_to :depot
end
#app/models/retailer.rb
class Retailer < ActiveRecord::Base
has_many :locations
end
这里有两个对应的fixtures文件:
#spec/fixtures/locations.yml
loc_paris:
retailer: ret_europe (Retailer)
name: "Paris"
nickname: "paris"
loc_washington:
retailer: ret_usa (Retailer)
name: "Washington"
nickname: "washington"
#spec/fixtures/retailers.yml
ret_europe:
name: "AcmeCo France"
nickname: "acmecofr"
currency_type: "EUR"
ret_usa:
name: "AcmeCo USA"
nickname: "acmecousa"
currency_type: "USD"
根据以上数据,运行pp locations(:loc_paris)会得到:
#<Location:0x0000000006eee1d8
id: 35456173,
name: "Paris",
nickname: "paris",
retailer_id: 399879241,
created_at: Wed, 23 May 2018 22:39:56 UTC +00:00,
updated_at: Wed, 23 May 2018 22:39:56 UTC +00:00>
这些 id 编号在多次调用中是一致的,至少在相同的 RSpec 上下文中是这样。 (我将pp locations(:loc_paris) 放在let 块中。)然而pp locations(:loc_paris).retailer 返回nil。
我尝试使用 FactoryBot,但我们不得不放弃它。我正在尝试对固定装置进行诚实的调整,但似乎我们最好在实际测试代码中简单地构建数据对象......因为该解决方案可以毫无怨言地工作:/
我在这里做错了吗?我们对固定装置的要求是否过高?
谢谢!
汤姆
【问题讨论】:
-
在 rspec 运行中,ID 是“随机的”还是顺序更高?您可以在运行此测试的位置包含一个完整的 rspec 文件吗?在您测试 location.retailer 的同一块中,您是否也可以运行“pp 零售商(:ret_europe)”,运行 .valid?针对这两个对象,看看您是否有某种验证错误。总而言之,这通常应该有效,所以不知道为什么它不会。哦,您能否确认您也在表上实施参照完整性?
-
虽然答案解决了问题,但我确实想指出,项目中的其他一些类(不是这些类)有一些在 before_validation 处理程序中运行的代码,它期望存在某些关联.在正常的应用程序工作流程中,这不是问题,但我注意到使用固定装置构建相同的对象可能会出现问题,因为不存在那些预期的关联。我会进一步研究,但这有点令人费解,因为包含的样本没有任何这样的逻辑并且仍然存在问题。
-
另外,我不知道 postgres-enforced CREATE PRIMARY KEY 之类的,AR 应该在 Ruby 端处理它。还是随着新版本的 Rails 发生变化?该项目最初是从 4.1 升级而来的。
标签: ruby-on-rails ruby tdd fixtures