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
相反,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_state
和 aasm_event
)是类方法,因此具有该状态机的类的每个实例都具有相同的状态。我希望“WorkItem”或“TaskList”能够根据其所拥有的任务动态创建一系列状态和转换。
这将使我能够动态定义工作流程并将状态映射到任务。
状态机曾经这样使用过吗?看来这个 ruby 工作流程 gem 与我所描述的类似。
更新:我可以看到执行类似以下操作,但这似乎有点黑客:
@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?
) 委托给实现匿名类。
Question is, are state machines always defined statically (on classes)? Or is there a way for me to have it so each instance of the class with has it's own set of states?
I'm checking out Stonepath for implementing a Task Engine. I don't really see the distinction between "states" and "tasks" in there, so I'm thinking I could just map a Task directly to a state. This would allow me to be able to define task-lists (or workflows) dynamically, without having to do things like:
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
Instead, a WorkItem (the main workflow/task manager model), would just have many tasks. Then the tasks would work like states, so I could do something like this:
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
However, I can't do that with the aasm gem because those methods (aasm_state
and aasm_event
) are class methods, so every instance of the class with that state machine has the same states. I want it so a "WorkItem" or "TaskList" dynmically creates a sequence of states and transitions based on the tasks it has.
This would allow me to dynamically define workflows and just have states map to tasks.
Are state machines ever used like this? It seems that this ruby workflow gem is similar to what I'm describing.
Update: I can see doing something like the following, but it seems sort of hackish:
@implementation_state_machine = Class::new do
include AASM
aasm_initial_state :initial
tasks.each { |state| aasm_state :"#{task.name}"}
# ...
end
... where a property on my model would be implementation_state_machine
. I'd have to override method_missing
to delegate state-related methods (accepted_phase?
) to the implementation anonymous class.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,这看起来确实很老套而且很混乱。我最近编写了一个新的 gem,它允许您在决策设置中使用动态“to”转换。
因此,是否可以先将它们映射出来,然后使用决定设置来允许转换决定进入哪个新状态,而不是动态构建事件和转换?您还可以将 from 转换包装在数组中,这样您就不需要执行 :from =>;先前状态? "#{task.name}_phase" : "initial",你可以这样做 :from => [ :cool_task_phase, :initial ]
我发现首先列出你的转换和事件,可以让你更好地了解你的模型正在做什么。
请访问 http://github.com/ryanza/stateflow
希望您能找到一些用处的这个。
Yeah, that does seem very hacky and quite messy. I wrote a new gem recently that allows you to use dynamic 'to' transitions with a decision setting.
So instead of building your events and transitions dynamically, would be it be possible to map them out first, and use the decide setting to allow the transition decide which new state to enter? You can also wrap your from transition in an array so you wouldn't need to do :from => previous_state ? "#{task.name}_phase" : "initial", you could just do :from => [ :cool_task_phase, :initial ]
I find that setting out your transitions and events out first, allows you to get a greater picture on what your model is doing.
Check it out at http://github.com/ryanza/stateflow
Hopefully you can find some use out of this.
在我的实现中,状态机是一个哈希 https://github.com/mpapis/state_attr
你可以定义为许多状态属性,如您所愿
顺便说一句:在后台仍然有一个类,但仅作为属性的代理
In my implementation state machine is a hash https://github.com/mpapis/state_attr
you can define as many state attributes as you like
BTW: in the background there is still a class but only as a proxy to attribute