重构 使用 state_machine 有很多相似的 event 如何 DRY?

yesmeck · 2013年08月22日 · 最后由 yesmeck 回复于 2013年08月22日 · 3780 次阅读

大概代码是这样:

# app/models/concerns/member_state.rb
module MemberState
  extend ActiveSupport::Concern

  included do
    state_machine :member_state, initial: :initial, namespace: 'member' do
      event :event1 do
        transition :initial => :state1
      end

      event :event2 do
        transition :state1 => :state2
      end

      event :event3 do
        transition :state2 => :state3
      end

      ...
    end
  end
end

# app/models/concerns/admin_state.rb
module AdminState
  extend ActiveSupport::Concern

  included do
    state_machine :admin_state, initial: :initial, namespace: 'admin' do
      event :event1 do
        transition :initial => :state1
      end

      event :event2 do
        transition :state1 => :state2
      end

      event :event3 do
        transition :state2 => :state3
      end

      ...
    end
  end
end

# app/models/order.rb
class Order < ActiveRecord::Base
  include MemberState
  include AdminState

  ...
end

想要重用相同的 event 定义该如何做呢?

event :event do
    transition :initial => :state1 , :state1 => :state2 , :state2 => :state3
end

这样通过一个 event 事件就可以控制三个状态的跳转了

我是不是理解错了,你想实现的是多个模型的状态机事件公用嘛? 这个貌似无解,在 api 中没看到过

#2 楼 @lionzixuanyuan 我是想相同的事件和相同的状态转换能不能不重復写

#3 楼 @yesmeck 那你可以考虑下是否可以这样:让你的 MemberState 和 AdminState 都继承自一个 State 的父类,然后在这个父类中定义状态机

可是这个两个状态的名字不一样呀

#5 楼 @yesmeck 状态的名字不一样应该没有影响的,只要一个状态机事件中不出现一个状态可以迁移到多个状态的情况就可以了啊

@lionzixuanyuan = =我愚钝还是不大懂,能否给个示例看看

#7 楼 @yesmeck

event :event do
    transition :initial => :state1 , :initial => :state2
end

上述的情况是错误的,因为通过这个事件,无法确认 initial 状态到底要迁移到哪个状态,所以上面的这个事件必须要拆成两个,然后根据情况分别调用。

event :event do
    transition :state1 => :initial ,  :state1 => :initial
end

这种情况是允许的,你自己体会一下,应该就会有思路了

好吧,是我给的示例代码有问题,member_state 和 admin_state 是两个不同的状态,我并不是想把三个事件合成一个事件,而是,在这两个状态里会有相同的事件和状态转变,我是想能不能不要重复定义。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号