Have you ever had state transition requirements that required automatic chaining of transition changes? I've got a system that transitions to a "to_reviewer" state after it has been created.
In the "to_reviewer" state, a group of reviewers are presented the assignment and they may accept the assignment, or a project manager may assign the assignment to a reviewer: in either case, as soon as there is a reviewer assigned, the assignment transitions to the "reviewer" state.
However, if the system already has a reviewer assigned at the "created" event, then it should cascade the state transition change and go directly to "reviewer" without staying in "to_reviewer"
Having selected the Rubyist AASM gem to implement my state machine in this Ruby on Rails project, I expected that I would be able to use the :after options of the aasm_state statement. I got that idea from the README.rdoc for version 2.1.1, which lists "event:after" in the callback chain.
However, the :after callback is called on an event (aasm_event) and I can't find documentation on how to hook into that callback. Digging into the the code, I found the following syntax works correctly in my Assignment object (derived from ActiveRecord). The solution is to use the :after_event option in the aasm_state definition statement.
This first part defines the states:
aasm_state :to_reviewer, :after_enter => :check_reviewer
This next part defines the events:
aasm_event :created do
transitions :to => :to_reviewer, :from => [:task_created]
aasm_event :task_review do
transitions :to => :reviewer, :from => [:to_reviewer]
This last part is the definition of the :after_enter method:
task_review unless reviewer_id.blank?
Now, when the object is created, the aasm_current_state is "task_created". If the object receives the "created" event, it transitions to the "to_reviewer" state. However, after the object enters the "to_reviewer" state, the "check_task_reviewer" method advances the state again if a reviewer as been assigned (indicated by the presence of the reviewer_id).
Checking the code in the console, we get:
>> a = Assignment.new
=> (Assignment object information)
>> a.reviewer_id = 5
And we can see that the object transitioned through the "to_reviewer" state an on into the "reviewer"state.