是否存在Ruby / Rails状态机,当状态发生变化时执行事件转换?

时间:2010-12-31 21:03:14

标签: ruby ruby-on-rails-3 state-machine

希望这不是一个愚蠢的问题,我只是没有忽略Ruby / Rails状态机(AASM,Transitions,AlterEgo等)中的某些东西。

据我所知,这些状态机实现的前言是事件将被触发,并且将根据旧状态和新状态触发该事件的适当转换。但是,它们似乎没有相反的方式;假设用户想要将状态从“已创建”更改为“已分配”并且发生正确的转换,而不是触发导致当前状态转换为新状态的事件。

基本上,我希望用户能够从可用状态的选择框中选择一个新状态,并执行相应的转换,警卫,成功回调等。

有谁知道现有的状态机实现是否支持这个?

2 个答案:

答案 0 :(得分:2)

状态机本质上不允许您任意跳转到系统中的任何状态。每个都有一个入口点,每次你想改变状态时,都会评估一些条件(其中一个可能是输入事件),下一个状态是这些条件的结果。但是,您可以拥有一个状态机,其中从每个状态到另一个状态定义了转换。

class Ticket
  acts_as_state_machine :initial => :new

  state :new
  state :open
  state :resolved

  event :open do
    transitions :to => :open, 
      :from => [:new, :resolved], :guard => :can_be_open?
  end

  event :new do
    transitions :to => :new, 
      :from => [:open, :resolved], :guard => :can_be_new?
  end

  event :resolved do
    transitions :to => :resolved,
      :from => [:open, :new], :guard => :can_be_resolved?
  end

  private

  def can_be_resolved?
    !resolution.blank?
  end

  ...

end

@ticket = Ticket.create
@ticket.state # => new
@ticket.resolved!
@ticket.state # => resolved

因此,您需要从下拉列表中检查所需的状态,并因此调用正确的转换。您可以使用像attr_accessor :new_state这样简单的内容,然后使用模型调用new_state => event的{​​{1}}映射或case语句。

答案 1 :(得分:0)

你可以用我的gem flojo完成你想要做的事情。 只需在状态之后命名事件,并让这些事件触发从通配符状态到下拉列表中所选状态的转换。

如果您的下拉列表中有“待处理”状态,则可以使用以下代码段配置flojo事件

event :pending do
  # :any is a wildcard state and is only valid as a begin state.
  transition :any, :pending
end

提交表单后,您必须使用“wf_”前缀“pending”,将其转换为符号,然后将其发送到您的对象。在类中创建一个执行前缀和符号转换的方法会更简洁,然后委托发送。

your_object.send :wf_pending

https://github.com/alternegro/flojo