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

Commit

Permalink
Add the ability to lazy load a service #4
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin committed Aug 5, 2013
1 parent 2325ac0 commit fc0dc88
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 9 deletions.
37 changes: 37 additions & 0 deletions examples/lazy_load_object.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require 'dependency_injection/container'
require 'dependency_injection/loaders/yaml'

c = DependencyInjection::Container.new
loader = DependencyInjection::Loaders::Yaml.new(c)
loader.load(File.join(File.dirname(File.expand_path(__FILE__)), 'lazy_load_object.yml'))

class NewsletterManager
def initialize(mailer)
@mailer = mailer
end

def send_mail(message)
puts 'newletter'
@mailer.send_mail(message)
end
end

class Mailer
def initialize
puts 'mailer loaded'
end

def send_mail(message)
puts "mail sent via: #{message}"
end
end

puts c.get('my.mailer').class
# => ProxyObject
puts c.get('my.newsletter_manager').class
# => NewsletterManager

c.get('my.newsletter_manager').send_mail('Hello World')
# => newsletter
# mailer loaded
# mail sent : Hello World
8 changes: 8 additions & 0 deletions examples/lazy_load_object.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
services:
my.mailer:
class: Mailer
lazy: true
my.newsletter_manager:
class: NewsletterManager
arguments:
- '@my.mailer'
6 changes: 4 additions & 2 deletions lib/dependency_injection/container.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'dependency_injection/alias_definition'
require 'dependency_injection/definition'
require 'dependency_injection/lazy_definition'

module DependencyInjection
class Container
Expand All @@ -20,8 +21,9 @@ def get(name)
end
end

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

This comment has been minimized.

Copy link
@cveneziani

cveneziani Aug 8, 2013

Just noticed that there's a missing white space here.
And don't you need to align these two assignations?

end

def register_alias(name, alias_definition_name)
Expand Down
12 changes: 12 additions & 0 deletions lib/dependency_injection/lazy_definition.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require 'dependency_injection/definition'
require 'dependency_injection/proxy_object'

module DependencyInjection
class LazyDefinition < Definition
def object
return @proxy_object if @proxy_object

@proxy_object = ProxyObject.new { super }
end
end
end
3 changes: 2 additions & 1 deletion lib/dependency_injection/loaders/yaml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ def add_service(name, parameters)
end

def add_standard_service(name, parameters)
definition = @container.register(name, parameters['class'])
lazy_load = parameters['lazy'] || false
definition = @container.register(name, parameters['class'], lazy_load)
definition.add_arguments(*parameters['arguments']) if parameters['arguments']
if (configurator = parameters['configurator'])
definition.add_configurator(configurator[0], configurator[1])
Expand Down
11 changes: 11 additions & 0 deletions lib/dependency_injection/proxy_object.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module DependencyInjection
class ProxyObject
def initialize(&block)
@object = block
end

def method_missing(method_name, *args)
@object.call.send(method_name, *args)
end
end
end
27 changes: 21 additions & 6 deletions test/dependency_injection/loaders/test_yaml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,33 +70,48 @@ def test_adding_service_with_alias_parameters
@yaml_loader.send(:add_service, 'my_alias', { 'alias' => 'my_definition' })
end

def test_adding_standard_service_as_lazy
@container.expects(:register).with('my_lazy_definition', 'MyLazyDefinition', true)
@yaml_loader.send(:add_standard_service, 'my_lazy_definition', { 'class' => 'MyLazyDefinition', 'lazy' => true })
end

def test_adding_standard_service_as_not_lazy
@container.expects(:register).with('my_definition', 'MyDefinition', false)
@yaml_loader.send(:add_standard_service, 'my_definition', { 'class' => 'MyDefinition', 'lazy' => false })
end

def test_adding_standard_service_with_default_lazy_value
@container.expects(:register).with('my_definition', 'MyDefinition', false)
@yaml_loader.send(:add_standard_service, 'my_definition', { 'class' => 'MyDefinition' })
end

def test_adding_standard_service_without_parameters
definition = mock
@container.stubs(:register).with('key_1', 'MyKlass').returns(definition)
@container.stubs(:register).with('key_1', 'MyKlass', false).returns(definition)
definition.expects(:add_arguments).never

@yaml_loader.send(:add_standard_service, 'key_1', { 'class' => 'MyKlass' })
end

def test_adding_standard_service_with_parameters
definition = mock
@container.stubs(:register).with('key_1', 'MyKlass').returns(definition)
@container.stubs(:register).with('key_1', 'MyKlass', false).returns(definition)
definition.expects(:add_arguments).with('arg_1', 'arg_2')

@yaml_loader.send(:add_standard_service, 'key_1', { 'class' => 'MyKlass', 'arguments' => ['arg_1', 'arg_2'] })
end

def test_adding_standard_service_without_method_calls
definition = mock
@container.stubs(:register).with('key_1', 'MyKlass').returns(definition)
@container.stubs(:register).with('key_1', 'MyKlass', false).returns(definition)
definition.expects(:add_method_call).never

@yaml_loader.send(:add_standard_service, 'key_1', { 'class' => 'MyKlass' })
end

def test_adding_standard_service_with_method_calls
definition = mock
@container.stubs(:register).with('key_1', 'MyKlass').returns(definition)
@container.stubs(:register).with('key_1', 'MyKlass', false).returns(definition)
definition.expects(:add_method_call).with('method_1', 'arg_1')
definition.expects(:add_method_call).with('method_2', 'arg_1', 'arg_2')
definition.expects(:add_method_call).with('method_3', %w(arg_1 arg_2))
Expand All @@ -108,15 +123,15 @@ def test_adding_standard_service_with_method_calls

def test_adding_standard_service_without_configurator
definition = mock
@container.stubs(:register).with('key_1', 'MyKlass').returns(definition)
@container.stubs(:register).with('key_1', 'MyKlass', false).returns(definition)
definition.expects(:add_configurator).never

@yaml_loader.send(:add_standard_service, 'key_1', { 'class' => 'MyKlass' })
end

def test_adding_standard_service_with_configurator
definition = mock
@container.stubs(:register).with('key_1', 'MyKlass').returns(definition)
@container.stubs(:register).with('key_1', 'MyKlass', false).returns(definition)
definition.expects(:add_configurator).with('ConfiguratorKlass', 'method_name')

@yaml_loader.send(:add_standard_service, 'key_1', { 'class' => 'MyKlass', 'configurator' => ['ConfiguratorKlass', 'method_name'] })
Expand Down
5 changes: 5 additions & 0 deletions test/dependency_injection/test_container.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ def test_registering_a_definition
assert_equal({ 'my_definition' => @definition }, @container.definitions)
end

def test_registering_a_lazy_definition
DependencyInjection::LazyDefinition.stubs(:new).with('MyLazyDefinition', @container)
@container.register('my_lazy_definition', 'MyLazyDefinition', true)
end

def test_registering_a_class_return_a_definition_object
assert_equal(@definition, @container.register('my_definition', 'MyDefinition'))
end
Expand Down
13 changes: 13 additions & 0 deletions test/dependency_injection/test_lazy_definition.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require 'test_helper'
require 'dependency_injection/lazy_definition'

class TestLazyDefinition < Minitest::Test
def setup
@container = mock
@lazy_definition = DependencyInjection::LazyDefinition.new('MyKlass', @container)
end

def test_getting_object_returns_a_proxy_object
assert_equal(DependencyInjection::ProxyObject, @lazy_definition.object.class)
end
end
15 changes: 15 additions & 0 deletions test/dependency_injection/test_proxy_object.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'test_helper'
require 'dependency_injection/proxy_object'

class TestProxyObject < Minitest::Test
def setup
@object = mock
@proxy_object = DependencyInjection::ProxyObject.new { @object }
end

def test_calling_a_method_existing_on_object
@object.expects(:existing_method).with('arg_1', 'arg_2')

@proxy_object.existing_method('arg_1', 'arg_2')
end
end

0 comments on commit fc0dc88

Please sign in to comment.