我有一个用例,我想根据所包含的特征操作工厂中的瞬态属性。有没有办法做到这一点,还是有更好的方法来做我想要完成的事情?
让我们说我正在构建一个House
对象。 house
可以包含多个windows
。我想创建一些自动创建一些窗口的子工厂,但我希望能够为特定类型的窗口添加特征。 window_types
transient属性实际上是window
工厂的特征列表。
factory :house do
floors 3
exterior 'Brick'
transient do
window_types { [:bay, :double_hung] }
end
trait :with_picture_window do
window_types.push(:picture)
end
factory :ranch_house do
floors 1
after(:create) do |house, evaluator|
evaluator.window_types.each do |window_type|
FactoryGirl.create :window, window_type
end
end
end
factory :mountain_house do
floors 2
exterior 'Log'
after(:create) do |house, evaluator|
evaluator.window_types.each do |window_type|
FactoryGirl.create :window, window_type
end
end
end
end
factory :window do
material 'Glass'
trait :bay do
# bay window attributes
end
trait :double_hung do
# double hung window attributes
end
trait :picture do
# picture window attributes
end
end
这会在NoMethodError: undefined method 'push' for #<FactoryGirl::Declaration::Implicit>
特征中引发:with_picture_window
错误。
为了论证,假设我做需要这些房屋的不同工厂。有没有办法可以在特征中修改 window_types 瞬态属性,然后将这个瞬态属性反映在我的子工厂中?
我希望能够做到:
FactoryGirl.create :ranch_house
# creates a ranch house with only bay and double_hung windows
FactoryGirl.create :ranch_house, :with_picture_window
# creates a ranch house with bay, double_hung, AND picture windows
如果没有,是否有更好的方法可以实现这一目标?
非常感谢提前。
答案 0 :(得分:2)
我能够根据Ben提出的想法找到合适的解决方案。我使用本地数组变量来存储需要创建的窗口类型。每个窗口的特征为after(:build)
块中的数组添加一种窗口。然后,在after(:create)
块中,我实际创建了窗口记录。
第一个after(:build)
块(不在trait
中的块)很重要,因为它会在对象创建之间重置window_types
数组。
FactoryGirl.define do
window_types = []
factory :house do
floors 3
exterior 'Brick'
after(:build) do
window_types = []
end
after(:create) do |house|
window_types.each do |window_type|
FactoryGirl.create(:window, window_type, house: house)
end
end
trait :with_picture_window do
after(:build) do
window_types << :picture
end
end
trait :with_double_hung_window do
after(:build) do
window_types << :double_hung
end
end
trait :with_bay_window do
after(:build) do
window_types << :bay
end
end
factory :house_with_bay_and_picture_window, traits: [:bay, :picture]
end
end
我很好奇听到有关此方法的任何想法。目前,这符合我的需求并且非常灵活。
答案 1 :(得分:1)
我不确定这会回答您的问题,但评论对格式限制无效。也许跟随模式可能有助于解决这个问题?
trait :with_window do
after(:build) do |house|
# Create a house window
house.windows << FactoryGirl.build(:window) #Presume you could also pass a window trait here.
end
after(:create) do |room|
# Clear the windows attached in after(:build) and create one without saving the house again
house.windows.each do |window|
window.house_id = house.id
window.save
end
house.reload
end
end
希望这能以某种方式提供帮助!