module StateManager::Resource

Public Class Methods

extended(base) click to toggle source
# File lib/state_manager/resource.rb, line 4
def self.extended(base)
  base.instance_eval do
    class_attribute :state_managers
    self.state_managers = {}

    attr_accessor :state_managers
  end

  base.send :include, InstanceMethods
end

Public Instance Methods

state_manager(property=:state, klass=nil, options={}, &block) click to toggle source
# File lib/state_manager/resource.rb, line 15
def state_manager(property=:state, klass=nil, options={}, &block)
  default_options = {:helpers => true}
  options = default_options.merge(options)

  klass ||= begin
    "#{self.name}States".constantize
  rescue NameError
    nil
  end
  klass ||= StateManager::Base

  # Create a subclass of the specified state manager and mixin an adapter
  # if a matching one is found
  this = self
  adapter = Adapters.match(self)
  resource_name = self.name.demodulize.underscore
  
  klass = Class.new(klass) do
    state_property property
    resource_class this
    resource_name resource_name
    include adapter.const_get('ManagerMethods') if adapter
    class_eval &block if block_given?
  end
  include adapter.const_get('ResourceMethods') if adapter

  # Callbacks
  state_manager_added(property, klass, options) if respond_to? :state_manager_added
  klass.added_to_resource(self, property, options)

  # Define the subclass as a constant. We do this for multiple reasons, one
  # of which is to allow it to be serialized to YAML for delayed_job
  const_name = "#{property.to_s.camelize}States"
  remove_const const_name if const_defined?(const_name, false)
  const_set(const_name, klass)

  # Create an accessor for the state manager on this resource
  state_managers[property] = klass
  property_name = "#{property.to_s}_manager"
  define_method property_name do
    state_manager = state_managers[property]
    unless state_manager
      state_manager = klass.new(self)
      state_managers[property] = state_manager
    end
    state_manager
  end

  # Define the helper methods on the resource
  Helpers::Methods.define_methods(klass.specification, self, property) if options[:helpers]
end