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

Lan*_*ard 5 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
Run Code Online (Sandbox Code Playgroud)

相反,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
Run Code Online (Sandbox Code Playgroud)

但是,我不能用aasm gem做到这一点因为那些方法(aasm_stateaasm_event)是类方法,所以具有该状态机的类的每个实例都具有相同的状态.我想要它,所以"WorkItem"或"TaskList"动态地根据它具有的任务创建一系列状态和转换.

这将允许我动态定义工作流程,并让状态映射到任务.

状态机是否曾经像这样使用过?看来这个ruby工作流宝石类似于我所描述的.

更新:我可以看到做类似以下的事情,但它似乎有点hackish:

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

  tasks.each { |state| aasm_state :"#{task.name}"}
  # ...
end
Run Code Online (Sandbox Code Playgroud)

......我的模型上的财产将是什么implementation_state_machine.我必须覆盖method_missing以将与状态相关的方法(accepted_phase?)委托给实现匿名类.

Rya*_*yan 2

是的,这看起来确实很老套而且很混乱。我最近编写了一个新的 gem,它允许您在决策设置中使用动态“to”转换。

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

我发现首先列出你的转换和事件可以让你更好地了解你的模型正在做什么。

请访问http://github.com/ryanza/stateflow查看

希望您能从中找到一些用处。