Search code examples
ruby-on-railsrubystate-machine

state-machines/state_machine - Next state in transitions


I'm using https://github.com/state-machines/state_machines for Rails for storing and doing work before and after a state change of an object.

What I'd like to do is have a single method which can be called in a before_transition for a given set of events, and for a given event, have the method called by the before_transition do something a bit differently.

For example, say the method is called log_state_change, something like:

def log_state_change
  case <???>
  when "successful"
    Rails.logger.info "Successful"
  when "failure"
    Rails.logger.info "Failure"
  when "starting_run"
    Rails.logger.info "Starting run" 
  else
    Rails.logger.error "Unknown"
end

I can find no methods that would fit for <???> above. Perhaps someone more familiar with this gem could assist please?


Solution

  • You can accept an argument on your before_transition callback and obtain all data you need to implement an expected behaviour.

    The code which passes the argument you can find at the source code of the library. You can implement this logic with around_transition as well.

    require 'state_machines'
    
    class Light
    
      state_machine :state, initial: :off do
    
        before_transition from: any, do: :log_me
    
        event :light do
          transition all => :on
        end
    
        event :dark do
          transition [:on] => :off
        end
    
      end
    
      def log_me(transition)
        case transition.event
        when :light
          p "`light` event was called to transition from #{transition.from} to #{transition.to}"
        when :dark
          p "`dark` event was called to transition from #{transition.from} to #{transition.to}"
        else
          p "`#{transition.event}` was called to transition from #{transition.from} to #{transition.to}"
        end
      end
    end
    
    a = Light.new
    
    a.light # => "`light` event was called to transition from off to on"
    a.dark # => "`dark` event was called to transition from on to off"