Commit 1b4b594

mo khan <mo@mokhan.ca>
2013-03-12 03:07:13
move container and proxy related code to containers folder
component.rb
@@ -0,0 +1,31 @@
+require 'lambda_behaviours'
+require "interceptor_registration"
+
+module Booty
+  class Component
+    include LambdaBehaviours
+
+    def initialize(class_key, &block)
+      @factory_method = block
+      @interceptors = []
+    end
+
+    def create(container)
+      instance = @factory_method.call(container)
+      @interceptors.each do |interceptor|
+        instance = interceptor.intercept(instance)
+      end
+      instance
+    end
+
+    def as_singleton
+      @factory_method = memoize(@factory_method)
+    end
+
+    def intercept(method)
+      interceptor = InterceptorRegistration.new(method)
+      @interceptors.push(interceptor)
+      interceptor
+    end
+  end
+end
container.rb
@@ -0,0 +1,51 @@
+require 'component'
+
+module Booty
+  class Container
+    def initialize
+      @items = {}
+      register(:container) { self }
+    end
+    def register(key, &block)
+      component = Component.new(key, &block)
+      components_for(key).push(component)
+      component
+    end
+    def resolve(key)
+      instantiate(components_for(key).first)
+    end
+    def resolve_all(key)
+      components_for(key).map {|item| instantiate(item) }
+    end
+    def build(type)
+      try("I could not create: #{type}"){ build!(type) }
+    end
+    def build!(type)
+      constructor = type.instance_method('initialize')
+      parameters = constructor.parameters.map do |req, parameter|
+        #logger.info("attempting to resolve #{parameter}")
+        resolve(parameter.to_sym)
+      end
+      type.send(:new, *parameters)
+    end
+
+    private
+
+    def components_for(key)
+      @items[key] = [] unless @items[key]
+      @items[key]
+    end
+    def instantiate(component)
+      component.create(self)
+    end
+    def try(error = nil, &lambda)
+      begin
+        lambda.call
+      rescue => e
+        error ||= "Oops: #{e}"
+        logger.error(error)
+        nil
+      end
+    end
+  end
+end
interceptor_registration.rb
@@ -0,0 +1,19 @@
+require 'proxy'
+
+module Booty
+  class InterceptorRegistration
+    def initialize(method_symbol)
+      @method = method_symbol
+    end
+
+    def with(interceptor)
+      @interceptor = interceptor
+    end
+
+    def intercept(instance)
+      proxy= Proxy.new(instance)
+      proxy.add(@method, @interceptor)
+      proxy
+    end
+  end
+end
invocation.rb
@@ -0,0 +1,15 @@
+module Booty
+  class Invocation
+    attr_reader :instance, :method, :arguments
+
+    def initialize(instance, method, args)
+      @instance = instance
+      @method = method
+      @arguments = args
+    end
+
+    def proceed
+      instance.send(@method, @arguments) 
+    end
+  end
+end
ioc.rb
@@ -0,0 +1,10 @@
+module Booty
+  class IOC
+    def self.bind_to(container)
+      @@container = container
+    end
+    def self.resolve(symbol)
+      @@container.resolve(symbol)
+    end
+  end
+end
proxy.rb
@@ -0,0 +1,19 @@
+require 'invocation'
+
+module Booty  
+  class Proxy
+    def initialize(instance)
+      @instance = instance
+    end
+
+    def add(method, interceptor)
+      self.class.define_method(method.to_sym) do |*args|
+        interceptor.intercept(create_invocation_for(method, args))
+      end
+    end
+
+    def create_invocation_for(method, args)
+      Invocation.new(@instance, method, args)
+    end
+  end
+end