Commit 1b4b594
2013-03-12 03:07:13
Changed files (6)
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