wirer 0.4.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rb +398 -0
- data/lib/wirer/container.rb +283 -0
- data/lib/wirer/dependency.rb +234 -0
- data/lib/wirer/errors.rb +30 -0
- data/lib/wirer/factory/class_mixins.rb +117 -0
- data/lib/wirer/factory/curried_dependencies.rb +33 -0
- data/lib/wirer/factory/from_args.rb +100 -0
- data/lib/wirer/factory/from_instance.rb +24 -0
- data/lib/wirer/factory/interface.rb +114 -0
- data/lib/wirer/factory/wrapped.rb +94 -0
- data/lib/wirer/service.rb +51 -0
- data/lib/wirer/version.rb +3 -0
- data/lib/wirer.rb +20 -0
- metadata +139 -0
@@ -0,0 +1,94 @@
|
|
1
|
+
module Wirer
|
2
|
+
# Allows an existing Factory to be wrapped with extra options for a specific context.
|
3
|
+
#
|
4
|
+
# See Factory#wrapped_with for a convenient way to construct one of these -- although you won't
|
5
|
+
# normally need to construct these yourself, rather a Container will wrap factories for you
|
6
|
+
# where you add them to the container together with specific options.
|
7
|
+
#
|
8
|
+
# Allows you to:
|
9
|
+
#
|
10
|
+
# * Specify additional :features that the wrapped factory provides in this context
|
11
|
+
# (eg to indicate that you provide a specific named version of a more general interface,
|
12
|
+
# a :special_logger rather than just a Logger)
|
13
|
+
#
|
14
|
+
# * Fix particular initial arguments that get passed to the factory when used in this wrapped context
|
15
|
+
# (eg if you have a factory that takes arguments, but you want to supply those args upfront,
|
16
|
+
# and get a factory that just constructs a particular singleton instance; 'currying')
|
17
|
+
#
|
18
|
+
# * Add extra requirements to the existing dependencies for this factory. Eg if you have a dependency on
|
19
|
+
# some general interface (eg Logger) and you want to pin it down to a specific named version that you've
|
20
|
+
# made available (like :special_context_logger). Or maybe you want to make an optional dependency into
|
21
|
+
# a non-optional one.
|
22
|
+
#
|
23
|
+
# * Give a constructor block which allows you customise the way the wrapped factory's new_from_dependencies
|
24
|
+
# method works. It gets passed the wrapped factory, the constructor dependencies and args, and should return
|
25
|
+
# the constructed instance. This is for when specifying :initial_args isn't enough and you need
|
26
|
+
# some custom way of supplying your pre-canned arguments when constructing the thing.
|
27
|
+
class Factory::Wrapped
|
28
|
+
include Factory::Interface
|
29
|
+
|
30
|
+
attr_reader :provides_features, :provides_class, :constructor_dependencies,
|
31
|
+
:wrapped_factory, :initial_args
|
32
|
+
|
33
|
+
OPTION_NAMES = [:args, :features, :dependencies].freeze
|
34
|
+
|
35
|
+
def initialize(factory, options={}, &wrapped_constructor_block)
|
36
|
+
@wrapped_factory = factory
|
37
|
+
|
38
|
+
@provides_class = factory.provides_class
|
39
|
+
|
40
|
+
@provides_features = factory.provides_features
|
41
|
+
extra = options[:features] and @provides_features |= extra
|
42
|
+
|
43
|
+
@constructor_dependencies = factory.constructor_dependencies.dup
|
44
|
+
|
45
|
+
setter_dependencies = factory.setter_dependencies(nil).dup
|
46
|
+
extra = options[:dependencies] and extra.each do |dep_name, extra_dep_args|
|
47
|
+
extra_dep_options = Dependency.normalise_arg_or_args_list(extra_dep_args)
|
48
|
+
if (dep = @constructor_dependencies[dep_name])
|
49
|
+
@constructor_dependencies[dep_name] = dep.with_options(extra_dep_options)
|
50
|
+
elsif (dep = setter_dependencies[dep_name])
|
51
|
+
setter_dependencies[dep_name] = dep.with_options(extra_dep_options)
|
52
|
+
# we only actually save this overridden set of setter_dependencies
|
53
|
+
# if at least one override is specified; otherwise we leave it delegating
|
54
|
+
# at runtime to the wrapped factory's setter_dependencies method,
|
55
|
+
# since this allows it to stay instance-sensitive. see #setter_dependencies.
|
56
|
+
@extended_static_setter_dependencies ||= setter_dependencies
|
57
|
+
else
|
58
|
+
raise Error, "No constructor_dependency or static setter_dependency #{arg_name.inspect} found to extend on the wrapped factory"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
if options[:args]
|
63
|
+
@initial_args = options[:args]
|
64
|
+
elsif wrapped_constructor_block
|
65
|
+
@wrapped_constructor_block = wrapped_constructor_block
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def setter_dependencies(instance=nil)
|
70
|
+
@extended_static_setter_dependencies || @wrapped_factory.setter_dependencies(instance)
|
71
|
+
end
|
72
|
+
|
73
|
+
def new_from_dependencies(dependencies, *other_args, &block_arg)
|
74
|
+
if @wrapped_constructor_block
|
75
|
+
@wrapped_constructor_block.call(dependencies, *other_args, &block_arg)
|
76
|
+
else
|
77
|
+
case @initial_args
|
78
|
+
when NilClass # forgeddit
|
79
|
+
when Array then other_args.unshift(*@initial_args)
|
80
|
+
else other_args.unshift(@initial_args)
|
81
|
+
end
|
82
|
+
@wrapped_factory.new_from_dependencies(dependencies, *other_args, &block_arg)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def inject_dependency(*args)
|
87
|
+
@wrapped_factory.inject_dependency(*args)
|
88
|
+
end
|
89
|
+
|
90
|
+
def post_initialize(*args)
|
91
|
+
@wrapped_factory.post_initialize(*args)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Wirer
|
2
|
+
# This is a small convenience superclass which you can (but needn't if you'd rather not)
|
3
|
+
# inherit from when making wireable classes.
|
4
|
+
#
|
5
|
+
# It comes pre-extended with Wirer::Factory::ClassDSL, and it defines initialize for
|
6
|
+
# you to save each constructor dependency in an appropriately-named instance variable.
|
7
|
+
# (note that the 'dependency' class method will also have declared an attr_reader
|
8
|
+
# with this name too, so you'll be able to get at it that way also.)
|
9
|
+
#
|
10
|
+
# Its 'new' method also type-checks the arguments to ensure that it has indeed
|
11
|
+
# been supplied with all the right dependencies that it was expecting.
|
12
|
+
# Since we have the metadata lying around for what is required, may as well take
|
13
|
+
# advantage of it. This is most handy if you're constructing instances manually
|
14
|
+
# rather than via a Wirer::Container -- eg in unit tests.
|
15
|
+
#
|
16
|
+
# It also sets a straightforward convention for arguments to the constructor:
|
17
|
+
# dependencies and other arguments are given in a single Hash argument.
|
18
|
+
class Service
|
19
|
+
extend Factory::ClassDSL
|
20
|
+
|
21
|
+
class << self
|
22
|
+
# new_from_dependencies, which the container uses, will skip any
|
23
|
+
# type-checking as the container is designed to supply the right dependencies.
|
24
|
+
alias :new_from_dependencies :new
|
25
|
+
|
26
|
+
def new(dependencies, *)
|
27
|
+
constructor_dependencies.each do |name, dependency|
|
28
|
+
dependency.check_argument(name, dependencies[name], true)
|
29
|
+
end
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
# this one will check that the relevant dependency arguments are passed,
|
34
|
+
# but won't check their types - useful if you want to pass in mocks for
|
35
|
+
# testing.
|
36
|
+
def new_skipping_type_checks(dependencies, *p, &b)
|
37
|
+
constructor_dependencies.each do |name, dependency|
|
38
|
+
dependency.check_argument(name, dependencies[name], false)
|
39
|
+
end
|
40
|
+
new_from_dependencies(dependencies, *p, &b)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(dependencies={})
|
45
|
+
raise ArgumentError, "expected a Hash of dependencies" unless dependencies.is_a?(Hash)
|
46
|
+
self.class.constructor_dependencies.each do |name, dependency|
|
47
|
+
instance_variable_set(:"@#{name}", dependencies[name])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/wirer.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Wirer
|
2
|
+
end
|
3
|
+
|
4
|
+
require 'wirer/factory/interface'
|
5
|
+
require 'wirer/factory/from_args'
|
6
|
+
require 'wirer/factory/wrapped'
|
7
|
+
require 'wirer/factory/from_instance'
|
8
|
+
require 'wirer/factory/class_mixins'
|
9
|
+
require 'wirer/factory/curried_dependencies'
|
10
|
+
require 'wirer/service'
|
11
|
+
require 'wirer/dependency'
|
12
|
+
require 'wirer/container'
|
13
|
+
require 'wirer/errors'
|
14
|
+
|
15
|
+
module Kernel
|
16
|
+
private
|
17
|
+
def Wirer(&block)
|
18
|
+
Wirer::Container.new(&block)
|
19
|
+
end
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wirer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 1
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 4
|
9
|
+
- 7
|
10
|
+
version: 0.4.7
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Matthew Willson
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-11-12 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rake
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: minitest
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ~>
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 11
|
43
|
+
segments:
|
44
|
+
- 2
|
45
|
+
- 1
|
46
|
+
- 0
|
47
|
+
version: 2.1.0
|
48
|
+
type: :development
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: mocha
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ~>
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 35
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
- 9
|
62
|
+
- 12
|
63
|
+
version: 0.9.12
|
64
|
+
type: :development
|
65
|
+
version_requirements: *id003
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
name: rcov
|
68
|
+
prerelease: false
|
69
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ~>
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
hash: 41
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
- 9
|
78
|
+
- 9
|
79
|
+
version: 0.9.9
|
80
|
+
type: :development
|
81
|
+
version_requirements: *id004
|
82
|
+
description:
|
83
|
+
email:
|
84
|
+
- matthew@playlouder.com
|
85
|
+
executables: []
|
86
|
+
|
87
|
+
extensions: []
|
88
|
+
|
89
|
+
extra_rdoc_files: []
|
90
|
+
|
91
|
+
files:
|
92
|
+
- lib/wirer.rb
|
93
|
+
- lib/wirer/version.rb
|
94
|
+
- lib/wirer/container.rb
|
95
|
+
- lib/wirer/dependency.rb
|
96
|
+
- lib/wirer/errors.rb
|
97
|
+
- lib/wirer/service.rb
|
98
|
+
- lib/wirer/factory/from_instance.rb
|
99
|
+
- lib/wirer/factory/curried_dependencies.rb
|
100
|
+
- lib/wirer/factory/wrapped.rb
|
101
|
+
- lib/wirer/factory/interface.rb
|
102
|
+
- lib/wirer/factory/class_mixins.rb
|
103
|
+
- lib/wirer/factory/from_args.rb
|
104
|
+
- README.rb
|
105
|
+
homepage:
|
106
|
+
licenses: []
|
107
|
+
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
hash: 3
|
119
|
+
segments:
|
120
|
+
- 0
|
121
|
+
version: "0"
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
hash: 3
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
version: "0"
|
131
|
+
requirements: []
|
132
|
+
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 1.8.10
|
135
|
+
signing_key:
|
136
|
+
specification_version: 3
|
137
|
+
summary: A lightweight dependency injection framework to help wire up objects in Ruby
|
138
|
+
test_files: []
|
139
|
+
|