wirer 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|