无与 Rails 个固定装置的关联...如何修复?
Nil Associations with Rails Fixtures... how to fix?
我有一个使用 rspec/fixtures 的 Rails 5.1 项目,但我无法让固定装置加载与 belongs_to/has_one/has_many 关联的对象:我请求固定装置的对象返回了它的_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
这里有两个对应的灯具文件:
#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
returns nil
.
我尝试使用 FactoryBot,但我们不得不放弃它。我试图给 fixtures 一个诚实的摇晃,但似乎我们最好只是在实际测试代码中构建数据对象......因为该解决方案没有抱怨:/
我是不是做错了什么?我们是不是对固定装置要求太多了?
谢谢!
汤姆
灯具问题
查看您的操作,locations(:loc_paris)
会找到 locations.yml 中描述的记录,但 locations(:loc_paris).retailer
不会。
Rails 协会是这样工作的:
locations(:loc_paris).retailer
将查找 locations(:loc_paris)
记录中提到的带有 retailer_id
的 retailer
。在你的情况下 retailer_id: 399879241
而这个 id
没有 reseller
这就是为什么 returns Nil
.
解法:
像这样描述灯具:
#spec/fixtures/locations.yml
loc_paris:
retailer_id: 1
name: "Paris"
nickname: "paris"
loc_washington:
retailer_id: 2
name: "Washington"
nickname: "washington"
#spec/fixtures/retailers.yml
ret_europe:
id: 1
name: "AcmeCo France"
nickname: "acmecofr"
currency_type: "EUR"
ret_usa:
id: 2
name: "AcmeCo USA"
nickname: "acmecousa"
currency_type: "USD"
现在,locations(:loc_paris).retailer
将查找 locations(:loc_paris)
记录中提到的 retailer_id
的零售商,即 retailer_id: 1
并且有一个经销商 ret_europe
id
。 问题已解决
当您 运行 rspec 时,首先 rspec
使用一些自动生成的 id
值将这些灯具保存到您的数据库中(如果 id
未明确提供),这就是为什么 id
和 reseller_id
是一些随机值 。如果你不希望 locations.yml
记录的 id
是一些随机值,你可以像这样自己提供:
loc_paris:
id: 1
retailer_id: 1
name: "Paris"
nickname: "paris"
提示:
作为 rspec
运行s 在 test
环境中(在 app/spec/rails_helper.rb 中提到)和我之前提到的每当你 运行 rspec
,首先它将灯具保存到您的数据库中。如果您的 local
和 test
数据库相同,fixtures 将替换您数据库的实际数据库记录。在您的情况下,locations
和 resellers
table 记录中的记录将被完全擦除并替换为这些固定装置。因此,为 test
环境创建不同的数据库。
希望这个回答对您有所帮助
我有一个使用 rspec/fixtures 的 Rails 5.1 项目,但我无法让固定装置加载与 belongs_to/has_one/has_many 关联的对象:我请求固定装置的对象返回了它的_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
这里有两个对应的灯具文件:
#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
returns nil
.
我尝试使用 FactoryBot,但我们不得不放弃它。我试图给 fixtures 一个诚实的摇晃,但似乎我们最好只是在实际测试代码中构建数据对象......因为该解决方案没有抱怨:/
我是不是做错了什么?我们是不是对固定装置要求太多了?
谢谢!
汤姆
灯具问题
查看您的操作,locations(:loc_paris)
会找到 locations.yml 中描述的记录,但 locations(:loc_paris).retailer
不会。
Rails 协会是这样工作的:
locations(:loc_paris).retailer
将查找 locations(:loc_paris)
记录中提到的带有 retailer_id
的 retailer
。在你的情况下 retailer_id: 399879241
而这个 id
没有 reseller
这就是为什么 returns Nil
.
解法: 像这样描述灯具:
#spec/fixtures/locations.yml
loc_paris:
retailer_id: 1
name: "Paris"
nickname: "paris"
loc_washington:
retailer_id: 2
name: "Washington"
nickname: "washington"
#spec/fixtures/retailers.yml
ret_europe:
id: 1
name: "AcmeCo France"
nickname: "acmecofr"
currency_type: "EUR"
ret_usa:
id: 2
name: "AcmeCo USA"
nickname: "acmecousa"
currency_type: "USD"
现在,locations(:loc_paris).retailer
将查找 locations(:loc_paris)
记录中提到的 retailer_id
的零售商,即 retailer_id: 1
并且有一个经销商 ret_europe
id
。 问题已解决
当您 运行 rspec 时,首先 rspec
使用一些自动生成的 id
值将这些灯具保存到您的数据库中(如果 id
未明确提供),这就是为什么 id
和 reseller_id
是一些随机值 。如果你不希望 locations.yml
记录的 id
是一些随机值,你可以像这样自己提供:
loc_paris:
id: 1
retailer_id: 1
name: "Paris"
nickname: "paris"
提示:
作为 rspec
运行s 在 test
环境中(在 app/spec/rails_helper.rb 中提到)和我之前提到的每当你 运行 rspec
,首先它将灯具保存到您的数据库中。如果您的 local
和 test
数据库相同,fixtures 将替换您数据库的实际数据库记录。在您的情况下,locations
和 resellers
table 记录中的记录将被完全擦除并替换为这些固定装置。因此,为 test
环境创建不同的数据库。
希望这个回答对您有所帮助