lib/adhearsion/component_manager.rb in adhearsion-0.8.3 vs lib/adhearsion/component_manager.rb in adhearsion-0.8.4
- old
+ new
@@ -1,43 +1,43 @@
module Adhearsion
module Components
-
+
mattr_accessor :component_manager
-
+
class ConfigurationError < Exception; end
-
+
class ComponentManager
-
+
class << self
-
+
def scopes_valid?(*scopes)
unrecognized_scopes = (scopes.flatten - SCOPE_NAMES).map(&:inspect)
raise ArgumentError, "Unrecognized scopes #{unrecognized_scopes.to_sentence}" if unrecognized_scopes.any?
true
end
-
+
end
-
+
SCOPE_NAMES = [:dialplan, :events, :generators, :rpc, :global]
-
+
attr_reader :scopes, :lazy_config_loader
def initialize(path_to_container_directory)
@path_to_container_directory = path_to_container_directory
@scopes = SCOPE_NAMES.inject({}) do |scopes, name|
scopes[name] = Module.new
scopes
end
@lazy_config_loader = LazyConfigLoader.new(self)
end
-
+
##
# Includes the anonymous Module created for the :global scope in Object, making its methods globally accessible.
#
def globalize_global_scope!
Object.send :include, @scopes[:global]
end
-
+
def load_components
components = Dir.glob(File.join(@path_to_container_directory + "/*")).select do |path|
File.directory?(path)
end
components.map! { |path| File.basename path }
@@ -48,13 +48,13 @@
load_file component_file
else
ahn_log.warn "Component directory does not contain a matching .rb file! Was expecting #{component_file.inspect}"
end
end
-
+
end
-
+
##
# Loads the configuration file for a given component name.
#
# @return [Hash] The loaded YAML for the given component name. An empty Hash if no YAML file exists.
#
@@ -65,143 +65,143 @@
YAML.load_file config_file
else
return {}
end
end
-
+
def extend_object_with(object, *scopes)
raise ArgumentError, "Must supply at least one scope!" if scopes.empty?
-
+
self.class.scopes_valid? scopes
-
+
scopes.each do |scope|
methods = @scopes[scope]
if object.kind_of?(Module)
object.send :include, methods
else
object.extend methods
end
end
object
end
-
+
def load_code(code)
load_container ComponentDefinitionContainer.load_code(code)
end
def load_file(filename)
load_container ComponentDefinitionContainer.load_file(filename)
end
-
+
protected
-
+
def load_container(container)
container.constants.each do |constant_name|
constant_value = container.const_get(constant_name)
Object.const_set(constant_name, constant_value)
end
metadata = container.metaclass.send(:instance_variable_get, :@metadata)
metadata[:initialization_block].call if metadata[:initialization_block]
-
+
self.class.scopes_valid? metadata[:scopes].keys
-
+
metadata[:scopes].each_pair do |scope, method_definition_blocks|
method_definition_blocks.each do |method_definition_block|
@scopes[scope].module_eval(&method_definition_block)
end
end
container
end
class ComponentDefinitionContainer < Module
-
+
class << self
def load_code(code)
returning(new) do |instance|
instance.module_eval code
end
end
-
+
def load_file(filename)
returning(new) do |instance|
instance.module_eval File.read(filename), filename
end
end
end
-
+
def initialize(&block)
# Hide our instance variables in the singleton class
metadata = {}
metaclass.send(:instance_variable_set, :@metadata, metadata)
-
+
metadata[:scopes] = ComponentManager::SCOPE_NAMES.inject({}) do |scopes, name|
scopes[name] = []
scopes
end
-
+
super
-
+
meta_def(:initialize) { raise "This object has already been instantiated. Are you sure you didn't mean initialization()?" }
end
-
+
def methods_for(*scopes, &block)
raise ArgumentError if scopes.empty?
-
+
ComponentManager.scopes_valid? scopes
-
+
metadata = metaclass.send(:instance_variable_get, :@metadata)
scopes.each { |scope| metadata[:scopes][scope] << block }
end
-
+
def initialization(&block)
# Raise an exception if the initialization block has already been set
metadata = metaclass.send(:instance_variable_get, :@metadata)
if metadata[:initialization_block]
raise "You should only have one initialization() block!"
else
metadata[:initialization_block] = block
end
end
alias initialisation initialization
-
+
protected
-
+
class << self
def self.method_added(method_name)
@methods ||= []
@methods << method_name
end
end
-
+
end
-
+
class ComponentMethodDefinitionContainer < Module
class << self
def method_added(method_name)
@methods ||= []
@methods << method_name
end
end
-
+
attr_reader :scopes
def initialize(*scopes, &block)
@scopes = []
super(&block)
end
-
+
end
-
+
class LazyConfigLoader
def initialize(component_manager)
@component_manager = component_manager
end
-
+
def method_missing(component_name)
config = @component_manager.configuration_for_component_named(component_name.to_s)
(class << self; self; end).send(:define_method, component_name) { config }
config
end
end
-
+
end
end
end