wirer 0.4.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+