lib/ruice/container.rb in ruice-0.1.1 vs lib/ruice/container.rb in ruice-0.2.0
- old
+ new
@@ -1,67 +1,116 @@
-# TODO:
-# - named dependencies
-# - dependency sets
-# - ???
module Ruice
class Dependency
- def initialize(target, require_new = false)
+ def initialize(target, is_fresh = false)
@target = target
- @require_new = require_new
+ @is_fresh = is_fresh
end
- attr_reader :target
- attr_reader :require_new
+ attr_reader :target, :is_fresh, :named
end
+ class Property
+ def initialize(name, default = nil)
+ @name = name
+ @default = default
+ end
+
+ attr_reader :name, :default
+ end
+
class Container
- def initialize
+ def initialize(properties = {}, env = 'default')
+ raise ArgumentError, 'Container properties can not be nil' if properties.nil?
+ raise ArgumentError, 'Container properties is not a Hash' unless properties.is_a? Hash
+ raise ArgumentError, 'Environment can not be nil' if env.nil?
+ raise ArgumentError, 'Environment must be a string' unless env.is_a? String
+
+ properties[:env] = env
+
+ @properties = properties
+ @env = env.to_sym
+
@bindings = {}
@instances = {}
end
- def request(target_class)
- return self if target_class == DIC::Container
+ attr_reader :env
- return @instances[target_class] if @instances.key? target_class
+ def lookup_property(name, default = nil)
+ path = name.split '.'
+ current = @properties
+ path.each do |key_part|
+ break if current.nil?
- instance = request_new target_class
+ raise Exception, 'Can not access value subkey for non-hash ' + current unless current.is_a? Hash
- @instances[target_class] = instance
+ sym_part = key_part.to_sym
+ current = current.fetch(sym_part, nil) || current.fetch(key_part, nil)
+ end
+
+ current || default
+ end
+
+ def request(name)
+ return self if name == Ruice::Container
+
+ return @instances[name] if @instances.key? name
+
+ instance = request_new name
+
+ @instances[name] = instance
+
instance
end
- def request_new(target_class)
- return self if target_class == DIC::Container
+ def request_new(name)
+ return self if name == Ruice::Container
- return @bindings[target_class].call self if @bindings.key? target_class
+ return @bindings[name].call self if @bindings.key? name
- instance = target_class.new
+ raise ArgumentError, 'Dependency name is not class, and no bindings are present' unless name.respond_to? :new
+
+ instance = name.new
vars = instance.instance_variables
vars.each do |it|
value = instance.instance_variable_get it
- next unless value.is_a? Dependency
+ next unless value.is_a?(Dependency) || value.is_a?(Property)
- replacement = if value.require_new
- request_new value.target
- else
- request value.target
- end
+ replacement = nil
+ replacement = lookup_property value.name, value.default if value.is_a? Property
+ if value.is_a? Dependency
+ replacement = if value.is_fresh
+ request_new value.target
+ else
+ request value.target
+ end
+ end
+
instance.instance_variable_set it, replacement
end
- instance.dic_ready(self) if instance.methods.include? :dic_ready
+ instance.dic_ready if instance.methods.include? :dic_ready
instance
end
- def attach(name, provider)
- raise ArgumentError, 'Argument must be instance of Proc' unless provider.is_a? Proc
+ def with(name, subject)
+ if subject.is_a? Proc
- @bindings[name] = provider
+ raise ArgumentError, 'Duplicate provider - ' + name if @bindings.key? name
+
+ @bindings[name] = subject
+ return
+ end
+
+ raise ArgumentError, 'Duplicate instance - ' + name if @instances.key? name
+
+ @instances[name] = subject
+
+ self
end
end
end