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

发布于 2024-08-25 18:01:13 字数 1667 浏览 6 评论 0原文

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

我正在查看 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 工作流程 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

阪姬 2024-09-01 18:01:13

是的,这看起来确实很老套而且很混乱。我最近编写了一个新的 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.

困倦 2024-09-01 18:01:13

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

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

你可以定义为许多状态属性,如您所愿

顺便说一句:在后台仍然有一个类,但仅作为属性的代理

In my implementation state machine is a hash https://github.com/mpapis/state_attr

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文