Dynamic state transition

64 views
Skip to first unread message

Fabio Kreusch

unread,
Jun 20, 2012, 8:00:38 AM6/20/12
to pluginaw...@googlegroups.com
Hi all! I have been looking for on how to implement a dynamic state transition for a situation like this: I have an object that retrieves a remote result, which can be successful or not. So, that object starts in the state :unprocessed, and when I call :process! it calls the remote service, and based on the result it can go to a state :successful or :failure. The thing is, it looks like state_machine does not support this.

This is a code sample of what I expect it to work like:

  class Transaction
    state_machine :status, :initial_state => :unprocessed do
      state :unprocessed, :successful, :failure

      event :process do
        # the state will depend on the existence of the authorization_code, which will be populated by an observer that calls a remote service
        transition :unprocessed => [:successful, :failure], :result => lambda { |transaction| transaction.authorization_code? ? :successful : :failure }
      end
    end
  end

  class TransactionObserver
    def before_process(transaction)
      result = RemoteService.process(transaction)
      
      if result.authorization?
        transaction.authorization_code = result.authorization
      end
    end
  end

I have seen some implementation suggestions that say to create an event for each different final state, and have a custom method for process!, but then I won't have the default callbacks and implementation that state_machine creates for events. Any thoughts about that?

Gurpartap Singh

unread,
Jun 24, 2012, 11:16:20 PM6/24/12
to pluginaw...@googlegroups.com
state :unprocessed, :authorized, :unauthorized

event :check do
  transition :processing => :authorized, :if => :authorization_valid?
  transition :processing => :unauthorized, :unless => :authorization_valid?
end

after_transition any => :processing,   :do => :check_authorization

def authorization_valid?
  @authorization
end

def check_authorization
  @authorization = RemoteService.process(transaction).authorization
end

You could also use :unprocessed instead of :unauthorized state, if your logic allows.

Regards

Gurpartap Singh

Gurpartap Singh

unread,
Jun 24, 2012, 11:17:39 PM6/24/12
to pluginaw...@googlegroups.com
Just for brevity:

    state :unprocessed, :processing, :authorized, :unauthorized
Reply all
Reply to author
Forward
0 new messages