ruby-on-railsrubyaasm

How to invoke Ruby gem AASM transition event given to and from states?


We have a Ruby on Rails application.

We're using Ruby's aasm gem to manage states of objects.

has_state
aasm do
    state :created, :initial => true
    state :submitted
    state :rejected
    state :approved

    event :submit do
        transitions :to => :submitted, :from => [:created]
    end

    event :mark_as_incomplete do
        transitions :to => :created, :from => [:submitted]
    end

    event :approve do
        transitions :to => :approved, :from => [:submitted]
    end

    event :reject do
        transitions :to => :rejected, :from => [:submitted]
    end
end

If we know an object's current state, which can be obtained using

object.aasm_current_state

and we also know the state to transition to, how can we invoke the event?

Please note, the from-state and to-state are variables, so we need to do the above dynamically. Of course, with certain to-state and from-state combination, the transition isn't available, in that case we should detect an error.

We're also assuming between any two state combination (to-state and from-state), there's only 1 event, I think theoretically there can be more than 1.

I think this can be achieved by delving into the innards of aasm source code, which, arguably, may not be a good practice. Any thoughts?

Just wonder if anyone has done this before.

Thanks!


Solution

  • There is no way provided by AASM to do this, but your own answer is getting already close enough to where you want to go. AASM is built around the assumption, that state machines allow multiple different transitions from one state to another.

    If the event name is not relevant for you, you could reuse the to-state name as event name, like this:

    aasm do
      ...
      event :approved do
        transitions :from => :submitted, :to => :approved
      end
      ...
    end
    

    By this you can fire the event by just knowing the to-state name

    approval_request.send(to_state)
    

    By default, AASM raises an exception if this transition is not allowed. If you don't like the exception, set whiny_transitions to false, like this:

    aasm :whiny_transitions => false do
       ...
    end