我在使用 Factory Girl
测试 StateMachine
时遇到了一些问题。看起来这取决于 Factory Girl 初始化对象的方式。
我是不是遗漏了什么,或者这不是应该的那么简单?
class Car < ActiveRecord::Base
attr_accessor :stolen # This would be an ActiveRecord attribute
state_machine :initial => lambda { |object| object.stolen ? :moving : :parked } do
state :parked, :moving
end
end
Factory.define :car do |f|
end
因此,初始状态取决于是否在初始化期间设置了stolen
属性。这似乎工作正常,因为 ActiveRecord 将属性设置为其初始化程序的一部分:
Car.new(:stolen => true)
## Broadly equivalent to
car = Car.new do |c|
c.attributes = {:stolen => true}
end
car.initialize_state # StateMachine calls this at the end of the main initializer
assert_equal car.state, 'moving'
然而,因为 Factory Girl 在单独设置其覆盖之前初始化对象(参见 factory_girl/proxy/build.rb ),这意味着流程更像是:
Factory(:car, :stolen => true)
## Broadly equivalent to
car = Car.new
car.initialize_state # StateMachine calls this at the end of the main initializer
car.stolen = true
assert_equal car.state, 'moving' # Fails, because the car wasn't 'stolen' when the state was initialized
最佳答案
您可以在您的工厂中添加一个 after_build 回调:
Factory.define :car do |c|
c.after_build { |car| car.initialize_state }
end
但是,我认为您不应该依赖于以这种方式设置您的初始状态。像 FactoryGirl 那样使用 ActiveRecord 对象是很常见的(即通过调用 c = Car.net; c.my_column = 123)。
我建议您允许您的初始状态为零。然后使用事件记录回调将状态设置为所需的值。
class Car < ActiveRecord::Base
attr_accessor :stolen # This would be an ActiveRecord attribute
state_machine do
state :parked, :moving
end
before_validation :set_initial_state, :on => :create
validates :state, :presence => true
private
def set_initial_state
self.state ||= stolen ? :moving : :parked
end
end
我认为这会给您带来更可预测的结果。
需要注意的是,使用未保存的 Car 对象会很困难,因为状态尚未设置。
关于ruby-on-rails - 使用 FactoryGirl 和 StateMachine 测试动态初始状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5728584/