工厂女孩 - 操纵瞬态属性
Factory Girl - Manipulate Transient Attribute
我有一个用例,我想根据包含的特征在工厂中操作瞬态属性。有没有办法做到这一点,或者有更好的方法来完成我想要完成的事情?
假设我正在构建一个 House
对象。 house
可以有多个windows
。我想创建一些会自动创建一些 windows 的子工厂,但我希望能够 添加特定类型 window 的特征。 window_types
瞬态属性实际上是 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
这从 :with_picture_window
特性中抛出一个 NoMethodError: undefined method 'push' for #<FactoryGirl::Declaration::Implicit>
错误。
为了论证,假设我确实需要不同的工厂来建造这些房子。有没有一种方法可以修改特征中的 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
如果没有,有没有更好的方法可以完成此操作?
非常感谢。
我不确定这是否会回答您的问题,但由于格式限制,评论将毫无用处。也许下面的模式可以解决这个问题?
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
希望这能以某种方式提供帮助!
我能够根据 Ben 提出的想法找到合适的解决方案。我使用了一个本地数组变量来存储需要创建的 windows 的类型。每个 window 的特征将 window 的类型添加到 after(:build)
块中的数组。然后,在 after(:create)
块中,我实际上创建了 window 记录。
第一个 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
我很想知道关于这种方法的任何想法。现在,这很适合我的需要,而且非常灵活。
我有一个用例,我想根据包含的特征在工厂中操作瞬态属性。有没有办法做到这一点,或者有更好的方法来完成我想要完成的事情?
假设我正在构建一个 House
对象。 house
可以有多个windows
。我想创建一些会自动创建一些 windows 的子工厂,但我希望能够 添加特定类型 window 的特征。 window_types
瞬态属性实际上是 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
这从 :with_picture_window
特性中抛出一个 NoMethodError: undefined method 'push' for #<FactoryGirl::Declaration::Implicit>
错误。
为了论证,假设我确实需要不同的工厂来建造这些房子。有没有一种方法可以修改特征中的 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
如果没有,有没有更好的方法可以完成此操作?
非常感谢。
我不确定这是否会回答您的问题,但由于格式限制,评论将毫无用处。也许下面的模式可以解决这个问题?
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
希望这能以某种方式提供帮助!
我能够根据 Ben 提出的想法找到合适的解决方案。我使用了一个本地数组变量来存储需要创建的 windows 的类型。每个 window 的特征将 window 的类型添加到 after(:build)
块中的数组。然后,在 after(:create)
块中,我实际上创建了 window 记录。
第一个 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
我很想知道关于这种方法的任何想法。现在,这很适合我的需要,而且非常灵活。