2010-03-21 6 views
5

Frage ist, sind State Machines immer statisch definiert (auf Klassen)? Oder gibt es eine Möglichkeit für mich, dass jede Instanz der Klasse ihre eigenen Zustände hat?Dynamische Zustandsmaschine in Ruby? Müssen Staatsmaschinen Klassen sein?

Ich überprüfe Stonepath für die Implementierung einer Task Engine. Ich sehe die Unterscheidung zwischen "Zuständen" und "Aufgaben" nicht wirklich, also denke ich, ich könnte eine Aufgabe direkt einem Staat zuordnen. Dies würde erlauben Sie mir, task-Listen (oder Workflows) in der Lage sein dynamisch zu definieren, ohne die Dinge zu tun zu haben, wie:

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 

Stattdessen ein WorkItem (das Haupt-Workflow/Task-Manager-Modell), würde nur viele Aufgaben. Dann würden die Aufgaben wie Staaten arbeiten, so kann ich so etwas tun:

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 

Allerdings kann ich das nicht mit den aasm gem, weil diese Methoden (aasm_state und aasm_event) sind Klassenmethoden, so dass jede Instanz Die Klasse mit dieser Zustandsmaschine hat dieselben Zustände. Ich will es so ein "WorkItem" oder "TaskList" erstellt dynamisch eine Sequenz von Zuständen und Übergängen basierend auf den Aufgaben, die es hat.

Dies würde mir erlauben, Arbeitsabläufe dynamisch zu definieren und nur Staaten Aufgaben zuzuordnen.

Werden Zustandsmaschinen jemals so verwendet? Es scheint, dass diese ruby workflow gem ähnlich ist, was ich beschreibe.

Update: Ich kann so etwas wie die folgenden sehen zu tun, aber es scheint eine Art hackish:

@implementation_state_machine = Class::new do 
    include AASM 
    aasm_initial_state :initial 

    tasks.each { |state| aasm_state :"#{task.name}"} 
    # ... 
end 

... wo eine Eigenschaft auf meinem Modell würde implementation_state_machine sein. Ich müsste method_missing überschreiben, um statusbezogene Methoden (accepted_phase?) an die anonyme Klasse der Implementierung zu delegieren.

Antwort

1

Ja, das scheint sehr hacky und ziemlich chaotisch. Ich habe kürzlich ein neues Juwel geschrieben, das es Ihnen ermöglicht, dynamische 'zu' Übergänge mit einer Entscheidungseinstellung zu verwenden.

Also, anstatt Ihre Ereignisse und Übergänge dynamisch zu erstellen, wäre es möglich, sie zuerst zu mappen, und die Entscheiden-Einstellung zu verwenden, um dem Übergang zu überlassen, welchen neuen Zustand einzugeben? Sie können auch den from-Übergang in ein Array einfügen, so dass Sie dies nicht tun müssten: from => previous_state? "# {task.name} _phase": "initial", du könntest einfach tun: from => [: cool_task_phase,: initial]

Ich finde, dass das Festlegen von Übergängen und Ereignissen zuerst, ermöglicht es Ihnen, eine zu bekommen ein besseres Bild davon, was Ihr Modell macht.

es Einchecken im http://github.com/ryanza/stateflow

aus Hoffentlich können Sie einige Nutzen aus dieser finden.

1

In meiner Implementierung Zustandsmaschine ist ein Hash https://github.com/mpapis/state_attr

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

können Sie festlegen, wie viele staatliche Attribute wie Sie

BTW mag: Im Hintergrund gibt es noch eine Klasse, sondern nur als Proxy Attribut

Verwandte Themen