2010-03-21 91 views
5

问题是,状态机总是静态定义(类)?还是有一种方法让我拥有它,这样每个类的实例都拥有它自己的一组状态?Ruby中的动态状态机?状态机必须是类吗?

我正在检出Stonepath以实现任务引擎。我并没有真正看到那里的“国家”和“任务”之间的区别,所以我想我可以直接将任务映射到一个状态。这将使我能够定义任务列表(或工作流程)动态,而无需做这样的事情:

aasm_event :evaluate do 
    transitions :to => :in_evaluation, :from => :pending 
end 

aasm_event :accept do 
    transitions :to => :accepted, :from => :pending 
end 

aasm_event :reject do 
    transitions :to => :rejected, :from => :pending 
end 

相反,工作项目(主要工作流程/任务管理器模式),也只是有很多任务。那么任务将工作像美国,所以我可以做这样的事情:

aasm_initial_state :initial 

tasks.each do |task| 
    aasm_state task.name.to_sym 
end 

previous_state = nil 
tasks.each do |tasks| 
    aasm_event task.name.to_sym do 
    transitions :to => "#{task.name}_phase".to_sym, :from => previous_state ? "#{task.name}_phase" : "initial" 
    end 
    previous_state = state 
end 

但是,我不能这样做与aasm gem,因为这些方法(aasm_stateaasm_event)是类方法,所以每一个实例该状态机的类具有相同的状态。我想要它,所以“WorkItem”或“TaskList”动态地创建一系列状态和基于它所具有的任务的转换。

这将允许我动态地定义工作流程,并且只将状态映射到任务。

状态机是否曾经这样使用?看起来这个ruby workflow gem与我所描述的相似。

更新:我可以看到做一些像下面,但似乎的排序的hackish:

@implementation_state_machine = Class::new do 
    include AASM 
    aasm_initial_state :initial 

    tasks.each { |state| aasm_state :"#{task.name}"} 
    # ... 
end 

...这里对我的模型的属性将是implementation_state_machine。我必须重写method_missing以将与状态相关的方法(accepted_phase?)委托给实现匿名类。

回答

1

是的,这似乎很hacky和相当混乱。我最近写了一个新的gem,允许你使用决策设置的动态'to'转换。

因此,不是动态构建事件和转换,而是可以先映射它们,并使用决定设置来允许转换决定进入哪个新状态?你也可以将你的转换封装在一个数组中,所以你不需要做:from => previous_state? “#{task.name} _phase”:“initial”,你可以这样做:from => [:cool_task_phase,:initial]

我发现首先设置你的转换和事件,关于你的模型正在做什么的更多图片。

瞧瞧吧http://github.com/ryanza/stateflow

希望你可以找到一些使用了这一点。

1

我在执行状态机是一种散列https://github.com/mpapis/state_attr

state_attr :state, { 
    nil => :first, 
    :first => [:second, :third], 
    :second => :last, 
    :third => nil, 
} 

你可以定义多达你喜欢

BTW状态属性:在后台还有一类,但只能作为代理属性