class Sinject::Container
This is the IOC Container
for registering all dependencies an building objects.
Attributes
instance[RW]
Public Class Methods
new(singleton=true)
click to toggle source
# File lib/sinject/container.rb, line 9 def initialize(singleton=true) @store = {} Sinject::Container.instance = self if singleton end
Public Instance Methods
get(key)
click to toggle source
Get an object from the container. This will build the requested object and all its dependencies.
Example:
>> Sinject::Container.instance.get :object_key
Arguments:
key: (Symbol)
# File lib/sinject/container.rb, line 86 def get(key) # get the dependency from the container store for the specified key item = @store[key] if !item.nil? # check if the item has been registered as a single instance item. if item.single_instance == true # check if the instance needs to be created item.instance = create_instance(item) if item.instance.nil? return item.instance else return create_instance(item) end else # no dependency has been registered for the specified key, # attempt to convert the key into a class name and initialize it. class_name = "#{key}".split('_').collect(&:capitalize).join puts "[#{self.class}] - WARNING: No registered dependency could be found for key: #{key}. " \ "Attempting to load class: #{class_name}." Object.const_get(class_name).new end end
is_registered?(key)
click to toggle source
@deprecated: Use registered? method instead
# File lib/sinject/container.rb, line 26 def is_registered?(key) puts "[#{self.class}] - #is_registered? method is deprecated please use #registered? instead." registered?(key) end
load_groups()
click to toggle source
# File lib/sinject/container.rb, line 109 def load_groups Sinject::DependencyGroup.descendants.sort_by(&:name).each do |g| group = g.new if (group.respond_to?(:valid?) && group.valid?) || (group.respond_to?(:is_valid?) && group.is_valid?) group.register(self) end end end
register(options = {}, &initialize_block)
click to toggle source
Register an object with the container. Objects can be registered as either a single instance or a multi instance object. Single instance objects are only initialized once and the same object is returned from the container for every request. Multi instance objects are a new instance that is created for each request.
Example:
>> Sinject::Container.instance.register { :key => :object_key, :class => ClassName, :singleton => true, :contract => ContractName }
Arguments:
key: (Symbol) class_name: (ClassName) single_instance: (Boolean)
# File lib/sinject/container.rb, line 43 def register(options = {}, &initialize_block) raise Sinject::DependencyRegistrationKeyNotSpecifiedException.new unless options.has_key?(:key) raise Sinject::DependencyRegistrationClassNotSpecifiedException.new unless options.has_key?(:class) key = options[:key] dependency_class_name = options[:class] # check if a dependency has already been registered for this key. raise Sinject::DependencyRegistrationException.new(key) if registered?(key) single_instance = false contract_class_name = nil if options != nil && options[:singleton] == true single_instance = true end if options != nil && options[:contract] != nil contract_class_name = options[:contract] end # Validate the dependency class against the contract if a contract has been specified validate_contract(dependency_class_name, contract_class_name) unless contract_class_name.nil? item = Sinject::ContainerItem.new item.key = key item.single_instance = single_instance item.class_name = dependency_class_name item.initialize_block = initialize_block @store[item.key] = item true end
registered?(key)
click to toggle source
Check if an object has been registered with the container.
Example:
>> Sinject::Container.instance.registered? :object_key => true
Arguments:
key: (Symbol)
# File lib/sinject/container.rb, line 22 def registered?(key) @store.has_key?(key) end
Private Instance Methods
create_instance(item)
click to toggle source
# File lib/sinject/container.rb, line 171 def create_instance(item) # check if a custom initializer block has been specified if item.initialize_block != nil # call the block to create the dependency instance instance = item.initialize_block.call # verify the block created the expected dependency type raise Sinject::DependencyInitializeException.new(item.class_name) unless instance.is_a?(item.class_name) else instance = item.class_name.new end instance end
match?(contract, dependency)
click to toggle source
# File lib/sinject/container.rb, line 163 def match?(contract, dependency) return true if contract[:type] == dependency[:type] return true if contract[:type] == :req && dependency[:type] == :opt return true if contract[:type] == :keyreq && dependency[:type] == :key false end
validate_contract(dependency_class, contract_class)
click to toggle source
# File lib/sinject/container.rb, line 120 def validate_contract(dependency_class, contract_class) # get the methods defined for the contract contract_methods = (contract_class.instance_methods - Object.instance_methods) # get the methods defined for the dependency dependency_methods = (dependency_class.instance_methods - Object.instance_methods) # calculate any methods specified in the contract that are not specified in the dependency missing_methods = contract_methods - dependency_methods if !missing_methods.empty? raise Sinject::DependencyContractMissingMethodsException.new(missing_methods) end # loop through each contract method contract_methods.each do |method| # get the contract method parameters contract_params = contract_class.instance_method(method).parameters.map{ |p| { type: p[0], name: p[1] } } # get the dependency method parameters dependency_params = dependency_class.instance_method(method).parameters.map{ |p| { type: p[0], name: p[1] } } errors = [] contract_params.each do |cp| dp = dependency_params.detect { |p| p[:name] == cp[:name] } if dp.nil? || !match?(cp, dp) errors << cp[:name] end end dependency_params.each do |dp| cp = contract_params.detect { |p| p[:name] == dp[:name] } if cp.nil? errors << dp[:name] end end # check if any parameter errors if errors.length > 0 raise Sinject::DependencyContractInvalidParametersException.new(method, errors) end end end