Ruby中的动态状态机?状态机必须是类吗?

时间:2010-03-21 03:56:09

标签: ruby state-machine workflow-engine

问题是,状态机总是是静态定义的(在类上)?或者有没有办法让我拥有它所以每个类的实例都拥有它自己的一组状态?

我正在检查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

相反,WorkItem(主工作流/任务管理器模型)只会有很多任务。然后任务就像状态一样工作,所以我可以这样做:

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?)委托给实现匿名类。

2 个答案:

答案 0 :(得分:1)

是的,这看起来确实非常黑客且非常混乱。我最近写了一个新的宝石,允许你使用动态'到'过渡决策设置。

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

我发现首先设置过渡和事件,可以让您更好地了解您的模型正在做什么。

http://github.com/ryanza/stateflow

上查看

希望你能找到一些用处。

答案 1 :(得分:1)

在我的实现中,状态机是哈希https://github.com/mpapis/state_attr

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

您可以根据需要定义任意数量的状态属性

BTW:在后台还有一个类,但只作为属性的代理