Skip to content
This repository has been archived by the owner on Apr 1, 2019. It is now read-only.

Commit

Permalink
WIP: Add scope in service #7
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin committed Sep 13, 2013
1 parent 4e96bac commit 5dcf6ed
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 9 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Another big drawback is that you have to instantiate as many objects as you have
Our two classes stay untouched, the only thing you have to do is to add a configuration file.

```yaml
# services.yml
# services.yml
parameters:
mailer.transporter: 'smtp'
services:
Expand Down Expand Up @@ -176,6 +176,12 @@ And here's some more details about each keyword:

* `alias`: A string containing the target service name.

* `scope`: A string defining the service initialization scope:
* `container`: a service is initialized only one time accross the container life (default)
* `prototype`: a new service is initialized each time you call the container

Note that the usage of a `prototype` service inside a `container` service raise a `ScopeWideningInjectionError`

__Please note:__
* You can reference a variable in the configuration with the following syntax: `%variable%`.
* You can reference declared services by prefixing it with an `@` sign.
Expand Down
2 changes: 1 addition & 1 deletion lib/dependency_injection/container.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def get(name)

def register(name, klass_name, lazy=false)
definition = lazy ? LazyDefinition.new(klass_name, self) : Definition.new(klass_name, self)
@definitions[name] =definition
@definitions[name] = definition
end

def register_alias(name, alias_definition_name)
Expand Down
29 changes: 22 additions & 7 deletions lib/dependency_injection/definition.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
require 'active_support/core_ext/string/inflections'
require 'dependency_injection/scope_widening_injection_error'

module DependencyInjection
class Definition
attr_accessor :arguments, :configurator, :klass_name, :method_calls
attr_accessor :arguments, :configurator, :klass_name, :method_calls, :scope

def initialize(klass_name, container)
@container = container
self.arguments = []
self.klass_name = klass_name
self.method_calls = {}
self.scope = :container
end

def add_argument(argument)
Expand Down Expand Up @@ -38,20 +40,30 @@ def klass
end

def object
return @object if @object
self.send("#{self.scope}_scoped_object")
end

private

def container_scoped_object
@object ||= initialize_object
end

@object = self.klass.new(*resolve(self.arguments))
def initialize_object
object = self.klass.new(*resolve(self.arguments))
self.method_calls.each { |method_name, arguments| @object.send(method_name, *resolve(arguments)) }
if self.configurator
name, method_name = self.configurator
configurator_object = resolve([name]).first
configurator_object.send(method_name, @object)
configurator_object.send(method_name, object)
end

@object
object
end

private
def prototype_scoped_object
initialize_object
end

def resolve(arguments)
resolve_references(resolve_container_parameters(arguments))
Expand All @@ -70,7 +82,10 @@ def resolve_container_parameters(arguments)
def resolve_references(arguments)
arguments.map do |argument|
if /^@(?<reference_name>.*)/ =~ argument
@container.get(reference_name)
reference = @container.get(reference_name)
raise ScopeWideningInjectionError if reference.scope == :prototype && scope == :container

reference
else
argument
end
Expand Down
1 change: 1 addition & 0 deletions lib/dependency_injection/loaders/yaml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def add_service(name, parameters)
def add_standard_service(name, parameters)
lazy_load = parameters['lazy'] || false
definition = @container.register(name, parameters['class'], lazy_load)
definition.scope = parameters['scope'] if parameters['scope']
definition.add_arguments(*parameters['arguments']) if parameters['arguments']
if (configurator = parameters['configurator'])
definition.add_configurator(configurator[0], configurator[1])
Expand Down
2 changes: 2 additions & 0 deletions lib/dependency_injection/scope_widening_injection_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ScopeWideningInjectionError < Error
end

0 comments on commit 5dcf6ed

Please sign in to comment.