Class: Dim::Container

Inherits:
Object
  • Object
show all
Defined in:
lib/dim.rb

Overview

Dim::Container is the central data store for registering services used for dependency injuction. Users register services by providing a name and a block used to create the service. Services may be retrieved by asking for them by name (via the [] operator) or by selector (via the method_missing technique).

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent = nil) ⇒ Container

Create a dependency injection container. Specify a parent container to use as a fallback for service lookup.



51
52
53
54
55
# File 'lib/dim.rb', line 51

def initialize(parent=nil)
  @services = {}
  @cache = {}
  @parent = parent || Container
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args, &block) ⇒ Object

Lookup a service by message selector. A service with the same name as sym will be returned, or an exception is thrown if no matching service is found.



104
105
106
# File 'lib/dim.rb', line 104

def method_missing(sym, *args, &block)
  self[sym]
end

Instance Attribute Details

#parentObject (readonly)

Returns the value of attribute parent.



47
48
49
# File 'lib/dim.rb', line 47

def parent
  @parent
end

Class Method Details

.service_block(name) ⇒ Object

Searching for a service block only reaches the Container class when all the containers in the hierarchy search chain have no entry for the service. In this case, the only thing to do is signal a failure.



124
125
126
# File 'lib/dim.rb', line 124

def self.service_block(name)
  fail(MissingServiceError, "Unknown Service '#{name}'")
end

Instance Method Details

#[](name) ⇒ Object

Lookup a service by name. Throw an exception if no service is found.



97
98
99
# File 'lib/dim.rb', line 97

def [](name)
  @cache[name] ||= service_block(name).call(self)
end

#clear_cache!Object

Resets the cached services



116
117
118
# File 'lib/dim.rb', line 116

def clear_cache!
  @cache = {}
end

#override(name, &block) ⇒ Object



76
77
78
# File 'lib/dim.rb', line 76

def override(name,&block)
  register(name,false,&block)
end

#register(name, raise_error_on_duplicate = true, &block) ⇒ Object

Register a service named name. The block will be used to create the service on demand. It is recommended that symbols be used as the name of a service.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/dim.rb', line 60

def register(name,raise_error_on_duplicate = true,&block)
  if @services[name]
    if raise_error_on_duplicate
      fail DuplicateServiceError, "Duplicate Service Name '#{name}'"
    else # delete the service from the cache
      @cache.delete(name)
    end
  end

  @services[name] = block

  self.class.send(:define_method, name) do
    self[name]
  end
end

#register_env(name, default = nil) ⇒ Object

Lookup a service from ENV variables, or use a default if given; fall back to searching the container and its parents for a default value



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/dim.rb', line 81

def register_env(name,default = nil)
  if value = ENV[name.to_s.upcase]
    register(name) { value }
  elsif default
    register(name) { default }
  else
    begin
      @parent.service_block(name)
    rescue MissingServiceError
      raise EnvironmentVariableNotFound, "Could not find an ENV variable named '#{name.to_s.upcase}' nor could we find a service named #{name} in the parent container"
    end
  end
end

#service_block(name) ⇒ Object

Return the block that creates the named service. Throw an exception if no service creation block of the given name can be found in the container or its parents.



111
112
113
# File 'lib/dim.rb', line 111

def service_block(name)
  @services[name] || @parent.service_block(name)
end

#service_exists?(name) ⇒ Boolean

Check to see if a custom method or service has been registered, returning true or false.

Returns:

  • (Boolean)


129
130
131
132
133
# File 'lib/dim.rb', line 129

def service_exists?(name)
  respond_to?(name) || service_block(name)
rescue Dim::MissingServiceError
  false
end

#verify_dependencies(*names) ⇒ Object

Given a list of services, check to see if they are available, returning true or false.



136
137
138
# File 'lib/dim.rb', line 136

def verify_dependencies(*names)
  names.all? { |name| service_exists?(name) }
end

#verify_dependencies!(*names) ⇒ Object

Given a list of services, check to see if they are available or raise an exception.



141
142
143
144
145
146
147
# File 'lib/dim.rb', line 141

def verify_dependencies!(*names)
  missing_dependencies = names.reject { |name| service_exists?(name) }

  unless missing_dependencies.empty?
    fail Dim::MissingServiceError, "Missing dependencies #{missing_dependencies.join(", ")}"
  end
end