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.
@@ -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
@@ -0,0 +1,3 @@
1
+ module Wirer
2
+ VERSION = '0.4.7'
3
+ 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
+