Ruby on rails 如何在FactoryBot中设置非';不是外键吗?
我正在使用FactoryBot(以前的FactoryGirl)为我的测试创建一些工厂数据。我有一个模型,通过模式(分解为相关内容)看起来像这样: 但是,Ruby on rails 如何在FactoryBot中设置非';不是外键吗?,ruby-on-rails,ruby,rspec,factory-bot,factory,Ruby On Rails,Ruby,Rspec,Factory Bot,Factory,我正在使用FactoryBot(以前的FactoryGirl)为我的测试创建一些工厂数据。我有一个模型,通过模式(分解为相关内容)看起来像这样: 但是,feature\u id和feature不是对要素对象的引用。。。它们只是线 我对工厂的定义如下: FactoryBot.define do factory :item do team "TheTeam" sequence(:feature_id) {|n| "Feature#{n}" } feature { Fake
feature\u id
和feature
不是对要素对象的引用。。。它们只是线
我对工厂的定义如下:
FactoryBot.define do
factory :item do
team "TheTeam"
sequence(:feature_id) {|n| "Feature#{n}" }
feature { Faker::Lorem.sentence }
end
end
> FactoryBot.create(:item, feature_id: "123", feature: "hi")
=> #<Item:0x007fad8d262810
id: 3,
team: "TheTeam",
feature_id: nil,
feature: nil,
created_at: Wed, 10 Jan 2018 02:45:01 UTC +00:00,
updated_at: Wed, 10 Jan 2018 02:45:01 UTC +00:00>
简单的例子是:
> FactoryBot.create(:item)
=> #<Item:0x007fad8cbfc048
id: 1,
team: "TheTeam",
feature_id: "Feature1",
feature: "Qui voluptatem animi et rerum et.",
created_at: Wed, 10 Jan 2018 02:40:01 UTC +00:00,
updated_at: Wed, 10 Jan 2018 02:40:01 UTC +00:00>
您可以看到功能现在是nil
。我假设这是因为它试图推断feature\u id
和feature
在某种程度上是相关的。但在这种情况下,我不想让他们这样
是否有更好的方法来定义工厂,使其仅将它们视为不相关的字段?
顺便说一句,如果我试图同时设置功能\u id
和功能
,它看起来是这样的:
FactoryBot.define do
factory :item do
team "TheTeam"
sequence(:feature_id) {|n| "Feature#{n}" }
feature { Faker::Lorem.sentence }
end
end
> FactoryBot.create(:item, feature_id: "123", feature: "hi")
=> #<Item:0x007fad8d262810
id: 3,
team: "TheTeam",
feature_id: nil,
feature: nil,
created_at: Wed, 10 Jan 2018 02:45:01 UTC +00:00,
updated_at: Wed, 10 Jan 2018 02:45:01 UTC +00:00>
>FactoryBot.create(:项目,功能\u id:“123”,功能:“hi”)
=> #
所以它只是将两个字段都设置为nil
。我怀疑FactoryBot试图根据这些字段的名称对其进行“智能化”。我想更改它们,但它们已经在数据库中设置为那样。看起来FactoryBot正在进行假设,而我还没有找到更改这些假设的方法。也许值得打开一个问题,看看维护人员能提供什么
同时,这里有一个解决方法:
FactoryBot.define do
FEATURE_IDS ||= (1..1000).cycle
factory :item do
team "TheTeam"
transient { without_feature_id false }
transient { without_feature false }
after(:build, :stub) do |item, evaluator|
item.feature_id = "Feature#{FEATURE_IDS.next}" unless evaluator.without_feature_id
item.feature = Faker::Lorem.sentence unless evaluator.without_feature
end
end
end
在上述情况下,这将正常工作
递增是很棘手的。我无法找到在资源构造上下文之外使用FactoryBot序列的方法,因此我使用枚举器并调用#next
来创建序列。这类似于FaseYbBOT序列,除了在测试运行期间没有重置为1的方式。
RSpec测试证明,无论我们是在数据库中创建项还是在内存中构建项,它都能按预期工作:
context 'when more than one item is created' do
let(:item_1) { create(:item) }
let(:item_2) { create(:item) }
it 'increments feature_id by 1' do
expect(item_1.feature_id).to be_present
expect(item_2.feature_id).to eq(item_1.feature_id.next)
end
end
context 'when using build instead of create' do
let(:item_1) { build(:item) }
let(:item_2) { build(:item) }
it 'increments feature_id by 1' do
expect(item_1.feature_id).to be_present
expect(item_2.feature_id).to eq(item_1.feature_id.next)
end
end
请注意,如果没有特征id或使用典型构造的特征,则无法创建项目;例如:
>> item = create(:item, feature_id: nil)
将导致
>> item.feature_id
#> "Feature1"
如果要创建不包含feature和feature_id字段的对象,可以执行以下操作:
create(:item, without_feature_id: true, without_feature: true)
如果在FactoryBot之外创建记录,此模型是否按预期工作?例如,如果您执行Item.create(团队:'TheTeam',feature_id:'123',feature:'Description of feature')
,是否会获得保存了所有属性的记录?好问题,@moveson。是的,它通过控制台工作,只需执行您在那里的操作。我没有任何字段验证,也没有任何关系(此时)。Item类不引用任何其他内容。所以Rails本身也可以使用它。这似乎是Factory中的某个功能。这看起来不错,但是否仍有办法在after()
块中获取功能id
的序列
部分?这是一个诡辩,但是如果功能\u id
是一个顺序递增的功能1
,功能2
,诸如此类的序列
就好了,我非常喜欢它!但是,我认为它可以是这样,而不是提供一个常量:item.feature\u id=“feature{item.class.count+1}”,除非evaluator.without\u feature\u id
,它只会在项目数上加1。因此,它不会重置,但在其他情况下应该可以工作。它确实会为每次创建添加一个额外的DB调用,但至少现在这不是问题。请记住,您可能不希望每次都在数据库中创建项。通常(希望非常经常)您只想使用build
或build\u stubbed
在内存中构建项。因此,我将避免依赖于数据库的增量值。也就是说,我错说了这个增量变量的工作方式。事实上,它将在测试运行开始时重置,而不是在每个单元测试开始时重置,这在任何情况下都可能是您想要的。。。好电话。是的,让它依赖于DB计数在这方面是有问题的。谢谢需要注意的一件有趣的事情是:如果我将属性更改为feature\u id
和feature\u title
,那么一切都可以在原始设置中运行。所以这肯定是因为X_id
和X
命名模式的缘故。