2010-03-21 86 views
5

問題是,狀態機總是靜態定義(類)?還是有一種方法讓我擁有它,這樣每個類的實例都擁有它自己的一組狀態?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 

相反,工作項目(主要工作流程/任務管理器模式),也只是有很多任務。那麼任務將工作像美國,所以我可以做這樣的事情:

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 workflow gem與我所描述的相似。

更新:我可以看到做一些像下面,但似乎的排序的hackish:

@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?)委託給實現匿名類。

回答

1

是的,這似乎很hacky和相當混亂。我最近寫了一個新的gem,允許你使用決策設置的動態'to'轉換。

因此,不是動態構建事件和轉換,而是可以先映射它們,並使用決定設置來允許轉換決定進入哪個新狀態?你也可以將你的轉換封裝在一個數組中,所以你不需要做:from => previous_state? 「#{task.name} _phase」:「initial」,你可以這樣做:from => [:cool_task_phase,:initial]

我發現首先設置你的轉換和事件,關於你的模型正在做什麼的更多圖片。

瞧瞧吧http://github.com/ryanza/stateflow

希望你可以找到一些使用了這一點。

1

我在執行狀態機是一種散列https://github.com/mpapis/state_attr

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

你可以定義多達你喜歡

BTW狀態屬性:在後臺還有一類,但只能作爲代理屬性