alaibe/big_machine

View on GitHub
lib/big_machine.rb

Summary

Maintainability
A
25 mins
Test Coverage
require "active_support/all"
require "forwardable"
require "big_machine/state"
require "big_machine/active_record"
require "big_machine/available_methods"
require "big_machine/lock"

module BigMachine
  extend ActiveSupport::Concern

  included do
    class_attribute :initial_state
    class_attribute :workflow

    if active_record_model?
      include BigMachine::ActiveRecord
    end
  end

  module ClassMethods
    def active_record_model?
      defined?(::ActiveRecord::Base) && self.ancestors.include?(::ActiveRecord::Base)
    end

    def big_machine(options)
      self.initial_state   = options[:initial_state]
      self.workflow        = options[:workflow]
      set_initial_state_class
    end

    def initial_state_class
      @initial_state_class
    end

    def set_initial_state_class
      @initial_state_class = self.initial_state.to_s.camelize.constantize
      include ::BigMachine::AvailableMethods
    end
  end

  def current_state
    set_current_state(self.class.initial_state_class) unless @current_state

    @current_state
  end

  def set_current_state(new_state_class)
    @current_state = new_state_class.new self

    forward_current_state
  end

  def forward_current_state
    extend SingleForwardable
    def_delegators :current_state, *current_state.class.available_methods
  end

  def transition_to(next_state_class, *args, &block)
    return unless current_state.exit *args

    previous_state = current_state
    set_current_state next_state_class

    rollback(previous_state) and return unless current_state.enter *args

    block.call self if block_given?
  end

  def rollback(previous_state)
    @current_state = @previous_state
  end

end