lib/big_machine.rb
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