needle 0.6.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/faq/faq.rb +143 -0
- data/doc/faq/faq.yml +75 -0
- data/doc/manual-html/chapter-1.html +26 -6
- data/doc/manual-html/chapter-2.html +39 -9
- data/doc/manual-html/chapter-3.html +177 -8
- data/doc/manual-html/chapter-4.html +108 -8
- data/doc/manual-html/chapter-5.html +28 -8
- data/doc/manual-html/chapter-6.html +28 -8
- data/doc/manual-html/chapter-7.html +29 -9
- data/doc/manual-html/chapter-8.html +176 -0
- data/doc/manual-html/index.html +26 -6
- data/doc/manual/manual.rb +1 -1
- data/doc/manual/manual.yml +7 -0
- data/doc/manual/parts/02_creating.txt +12 -2
- data/doc/manual/parts/03_conventional.txt +29 -0
- data/doc/manual/parts/03_locator.txt +60 -0
- data/doc/manual/parts/03_overview.txt +19 -0
- data/doc/manual/parts/04_overview.txt +9 -0
- data/doc/manual/parts/04_setup.txt +44 -0
- data/lib/needle/container.rb +68 -11
- data/lib/needle/registry.rb +25 -28
- data/lib/needle/service-point.rb +6 -1
- data/lib/needle/version.rb +1 -1
- data/test/models/model_test.rb +21 -1
- data/test/tc_container.rb +28 -1
- data/test/tc_registry.rb +22 -5
- data/test/tc_service_point.rb +9 -0
- metadata +11 -2
data/lib/needle/container.rb
CHANGED
@@ -41,7 +41,7 @@ module Needle
|
|
41
41
|
protected_instance_methods +
|
42
42
|
public_instance_methods -
|
43
43
|
[ "instance_eval", "__id__", "__send__", "initialize", "remove_const",
|
44
|
-
"method_missing", "inspect" ]
|
44
|
+
"method_missing", "method", "class", "inspect", "to_s", "instance_variables" ]
|
45
45
|
).
|
46
46
|
each { |m| undef_method m }
|
47
47
|
|
@@ -63,11 +63,9 @@ module Needle
|
|
63
63
|
@container.intercept( name )
|
64
64
|
end
|
65
65
|
|
66
|
-
# Delegate to Container#namespace.
|
67
|
-
# the new namespace, however, pass the definition context for the new
|
68
|
-
# container.
|
66
|
+
# Delegate to Container#namespace.
|
69
67
|
def namespace( *parms, &block )
|
70
|
-
@container.namespace( *parms
|
68
|
+
@container.namespace( *parms, &block )
|
71
69
|
end
|
72
70
|
|
73
71
|
# Delegate to Container#namespace!.
|
@@ -75,6 +73,11 @@ module Needle
|
|
75
73
|
@container.namespace!( *parms, &block )
|
76
74
|
end
|
77
75
|
|
76
|
+
# Delegate to Container#define on the new namespace.
|
77
|
+
def namespace_define( *parms, &block )
|
78
|
+
@container.namespace( *parms ) { |ns| ns.define( &block ) }
|
79
|
+
end
|
80
|
+
|
78
81
|
# Any method invocation with no block and no parameters is interpreted to
|
79
82
|
# be a service reference on the wrapped container, and delegates to
|
80
83
|
# Container#[]. If the block is not given but the args are not empty, a
|
@@ -125,8 +128,9 @@ module Needle
|
|
125
128
|
# container's name and all parent's names up to the root container,
|
126
129
|
# catenated together with dot characters, i.e., "one.two.three".
|
127
130
|
def fullname
|
128
|
-
|
129
|
-
|
131
|
+
parent_name = ( @parent ? @parent.fullname : nil )
|
132
|
+
return @name.to_s unless parent_name
|
133
|
+
"#{parent_name}.#{@name}"
|
130
134
|
end
|
131
135
|
|
132
136
|
# Returns the DefinitionContext instance that can be used to "build"
|
@@ -173,6 +177,8 @@ module Needle
|
|
173
177
|
# requested (with Container#[]), the associated callback will be used
|
174
178
|
# to construct it.
|
175
179
|
#
|
180
|
+
# This returns the registry that was used to register the service.
|
181
|
+
#
|
176
182
|
# Usage:
|
177
183
|
#
|
178
184
|
# container.register( :calc, :model=>:prototype ) do |c|
|
@@ -184,6 +190,8 @@ module Needle
|
|
184
190
|
name = name.to_s.intern unless name.is_a?( Symbol )
|
185
191
|
@service_points[ name ] =
|
186
192
|
ServicePoint.new( self, name, opts, &callback )
|
193
|
+
|
194
|
+
self
|
187
195
|
end
|
188
196
|
|
189
197
|
# Create a new namespace within the container, with the given name. If a
|
@@ -198,7 +206,7 @@ module Needle
|
|
198
206
|
#
|
199
207
|
# Note that this means that namespaces may be singletons or prototypes, or
|
200
208
|
# have immediate or deferred instantiation, and so forth. (The default of
|
201
|
-
#
|
209
|
+
# immediate, singleton instantiation is sufficient for 99% of the things
|
202
210
|
# you'll use namespaces for.)
|
203
211
|
#
|
204
212
|
# Usage:
|
@@ -209,6 +217,11 @@ module Needle
|
|
209
217
|
# end
|
210
218
|
#
|
211
219
|
# adder = container.calc.operations.add
|
220
|
+
#
|
221
|
+
# *Note*: the block is not invoked until the namespace is created, which
|
222
|
+
# is not until it is first referenced. If you need the namespace to be
|
223
|
+
# created immediately, either use #namespace_define or reference the
|
224
|
+
# namespace as soon as you've created it.
|
212
225
|
def namespace( name, opts={}, &block )
|
213
226
|
register( name, opts ) do |c,p|
|
214
227
|
ns = Container.new( c, name )
|
@@ -229,20 +242,64 @@ module Needle
|
|
229
242
|
#
|
230
243
|
# Note that this means that namespaces may be singletons or prototypes, or
|
231
244
|
# have immediate or deferred instantiation, and so forth. (The default of
|
232
|
-
#
|
245
|
+
# immediate, singleton instantiation is sufficient for 99% of the things
|
233
246
|
# you'll use namespaces for.)
|
234
247
|
#
|
235
248
|
# Usage:
|
236
249
|
#
|
237
|
-
# container.
|
250
|
+
# container.namespace_define!( :operations ) do
|
238
251
|
# add { Adder.new }
|
239
252
|
# ...
|
240
253
|
# end
|
241
254
|
#
|
242
255
|
# adder = container.calc.operations.add
|
243
|
-
|
256
|
+
#
|
257
|
+
# *Note*: this method will immediately instantiate the new namespace,
|
258
|
+
# unlike #namespace. If you want instantiation of the namespace to be
|
259
|
+
# deferred, either use a deferring service model
|
260
|
+
# (like <tt>:singleton_deferred</tt>) or create the namespace via
|
261
|
+
# #namespace.
|
262
|
+
def namespace_define!( name, opts={}, &block )
|
244
263
|
raise ArgumentError, "block expected" unless block
|
245
264
|
namespace( name, opts ) { |ns| ns.define!( &block ) }
|
265
|
+
self[name]
|
266
|
+
end
|
267
|
+
|
268
|
+
alias :namespace! :namespace_define!
|
269
|
+
|
270
|
+
# Create a new namespace within the container, with the given name.
|
271
|
+
# The block (which is required) will be passed to Container#define on
|
272
|
+
# the new namespace.
|
273
|
+
#
|
274
|
+
# For the curious, namespaces are simply services that are implemented
|
275
|
+
# by Container. The two statements are really identical:
|
276
|
+
#
|
277
|
+
# container.namespace( :calc )
|
278
|
+
# container.register( :calc ) { |c| Needle::Container.new( c, :calc ) }
|
279
|
+
#
|
280
|
+
# Note that this means that namespaces may be singletons or prototypes, or
|
281
|
+
# have immediate or deferred instantiation, and so forth. (The default of
|
282
|
+
# immediate, singleton instantiation is sufficient for 99% of the things
|
283
|
+
# you'll use namespaces for.)
|
284
|
+
#
|
285
|
+
# Usage:
|
286
|
+
#
|
287
|
+
# container.define_namespace( :operations ) do |b|
|
288
|
+
# b.add { Adder.new }
|
289
|
+
# ...
|
290
|
+
# end
|
291
|
+
#
|
292
|
+
# adder = container.calc.operations.add
|
293
|
+
#
|
294
|
+
# *Note*: this method will immediately instantiate the new namespace,
|
295
|
+
# unlike #namespace. If you want instantiation of the namespace to be
|
296
|
+
# deferred, either use a deferring service model
|
297
|
+
# (like <tt>:singleton_deferred</tt>) or create the namespace via
|
298
|
+
# #namespace.
|
299
|
+
def namespace_define( name, opts={}, &block )
|
300
|
+
raise ArgumentError, "block expected" unless block
|
301
|
+
namespace( name, opts ) { |ns| ns.define( &block ) }
|
302
|
+
self[name]
|
246
303
|
end
|
247
304
|
|
248
305
|
# Describe a new interceptor to use that will intercept method calls
|
data/lib/needle/registry.rb
CHANGED
@@ -28,7 +28,7 @@ module Needle
|
|
28
28
|
|
29
29
|
# Registry is a specialization of Container, with additional functionality
|
30
30
|
# for bootstrapping basic services into a new registry. It also supports a
|
31
|
-
# #
|
31
|
+
# #define! method for easily registering new services.
|
32
32
|
#
|
33
33
|
# Usage:
|
34
34
|
#
|
@@ -41,34 +41,41 @@ module Needle
|
|
41
41
|
# bar = registry.bar
|
42
42
|
class Registry < Container
|
43
43
|
|
44
|
-
# This is the default name given to a registry. If you have multiple
|
45
|
-
# independent registries in the same application, it can help to given them
|
46
|
-
# each names. By default, the name is empty.
|
47
|
-
DEFAULT_REGISTRY_NAME = ""
|
48
|
-
|
49
44
|
# Instantiate a new Registry (via #new) and immediately invoke #define!
|
50
45
|
# using the given block.
|
51
46
|
#
|
52
47
|
# Usage:
|
53
48
|
#
|
54
|
-
# registry = Needle::Registry.
|
49
|
+
# registry = Needle::Registry.define! do
|
55
50
|
# add { Adder.new }
|
56
51
|
# ...
|
57
52
|
# end
|
58
53
|
#
|
59
54
|
# adder = registry.add
|
60
|
-
def self.
|
55
|
+
def self.define!( *parms, &block )
|
61
56
|
raise NeedleError, "needs a block" if block.nil?
|
62
57
|
new( *parms ) { |reg| reg.define!( &block ) }
|
63
58
|
end
|
64
59
|
|
65
|
-
# Instantiate a new Registry
|
66
|
-
#
|
67
|
-
#
|
60
|
+
# Instantiate a new Registry (via #new) and immediately invoke #define
|
61
|
+
# using the given block.
|
62
|
+
#
|
63
|
+
# Usage:
|
64
|
+
#
|
65
|
+
# registry = Needle::Registry.define do |b|
|
66
|
+
# b.add { Adder.new }
|
67
|
+
# ...
|
68
|
+
# end
|
68
69
|
#
|
69
|
-
#
|
70
|
-
|
71
|
-
|
70
|
+
# adder = registry.add
|
71
|
+
def self.define( *parms, &block )
|
72
|
+
raise NeedleError, "needs a block" if block.nil?
|
73
|
+
new( *parms ) { |reg| reg.define( &block ) }
|
74
|
+
end
|
75
|
+
|
76
|
+
# Instantiate a new Registry. The options hash may include options
|
77
|
+
# used to initialize the logger factory. The logger factory options
|
78
|
+
# should be in another hash, keyed by the value <tt>:logs</tt>.
|
72
79
|
#
|
73
80
|
# If a block is given, the constructed registry instance is yielded to it.
|
74
81
|
#
|
@@ -87,25 +94,15 @@ module Needle
|
|
87
94
|
# registry = Needle::Registry.new(
|
88
95
|
# :logs => { :filename => "/dev/null" }
|
89
96
|
# )
|
90
|
-
def initialize(
|
91
|
-
|
92
|
-
name = ( parms.first.is_a?( String ) ? parms.shift :
|
93
|
-
DEFAULT_REGISTRY_NAME )
|
94
|
-
opts = ( parms.first.is_a?( Hash ) ? parms.shift : {} )
|
95
|
-
|
96
|
-
if parms.length > 0
|
97
|
-
raise ArgumentError, "invalid parameter(s): #{parms.inspect}"
|
98
|
-
end
|
99
|
-
|
100
|
-
super( nil, name )
|
97
|
+
def initialize( opts={} )
|
98
|
+
super( nil, nil )
|
101
99
|
bootstrap( opts )
|
102
|
-
|
103
100
|
yield( self ) if block_given?
|
104
101
|
end
|
105
102
|
|
106
|
-
#
|
103
|
+
# Returns +nil+. Registries are unnamed containers.
|
107
104
|
def fullname
|
108
|
-
|
105
|
+
nil
|
109
106
|
end
|
110
107
|
|
111
108
|
# Bootstraps the pipeline elements, service models, logger factory, and
|
data/lib/needle/service-point.rb
CHANGED
@@ -73,7 +73,12 @@ module Needle
|
|
73
73
|
# name, its container's name, and all of its container's ancestors' names
|
74
74
|
# concatenated together with dot characters, i.e. "one.two.three".
|
75
75
|
def fullname
|
76
|
-
|
76
|
+
container_name = @container.fullname
|
77
|
+
if container_name
|
78
|
+
"#{container_name}.#{@name}"
|
79
|
+
else
|
80
|
+
@name.to_s
|
81
|
+
end
|
77
82
|
end
|
78
83
|
|
79
84
|
# Adds the given interceptor definition to this service point. The
|
data/lib/needle/version.rb
CHANGED
data/test/models/model_test.rb
CHANGED
@@ -30,6 +30,10 @@ class ModelTest_MockService
|
|
30
30
|
@init_result = :initialized
|
31
31
|
end
|
32
32
|
|
33
|
+
def custom_init
|
34
|
+
@init_result = :custom
|
35
|
+
end
|
36
|
+
|
33
37
|
end
|
34
38
|
|
35
39
|
module ModelTest
|
@@ -65,7 +69,7 @@ module ModelTest
|
|
65
69
|
def assert_threaded
|
66
70
|
define_method( :extra_setup ) do
|
67
71
|
cache = Thread.current[:threaded_services]
|
68
|
-
cache.delete "
|
72
|
+
cache.delete "test" if cache
|
69
73
|
end
|
70
74
|
|
71
75
|
define_method( :test_multiplicity_singlethread ) do
|
@@ -109,10 +113,26 @@ module ModelTest
|
|
109
113
|
end
|
110
114
|
|
111
115
|
def assert_init
|
116
|
+
if instance_methods.include?( "extra_setup" )
|
117
|
+
save_setup = instance_method( :extra_setup )
|
118
|
+
end
|
119
|
+
|
120
|
+
define_method( :extra_setup ) do
|
121
|
+
save_setup.bind( self ).call if save_setup
|
122
|
+
@registry.register( :test_init, :model=>self.class.model,
|
123
|
+
:init_method=>:custom_init
|
124
|
+
) { ModelTest_MockService.new }
|
125
|
+
end
|
126
|
+
|
112
127
|
define_method( :test_initialize ) do
|
113
128
|
o = @registry[ :test ]
|
114
129
|
assert_equal :initialized, o.init_result
|
115
130
|
end
|
131
|
+
|
132
|
+
define_method( :test_custom_initialize ) do
|
133
|
+
o = @registry[ :test_init ]
|
134
|
+
assert_equal :custom, o.init_result
|
135
|
+
end
|
116
136
|
end
|
117
137
|
end
|
118
138
|
|
data/test/tc_container.rb
CHANGED
@@ -146,7 +146,7 @@ class TC_Container < Test::Unit::TestCase
|
|
146
146
|
|
147
147
|
container.define do |b|
|
148
148
|
b.test( :pipeline=>[] ) { Hash.new }
|
149
|
-
b.
|
149
|
+
b.namespace_define :subitem, :pipeline=>[] do |b2|
|
150
150
|
b2.test2( :pipeline=>[] ) { Hash.new }
|
151
151
|
end
|
152
152
|
end
|
@@ -192,6 +192,33 @@ class TC_Container < Test::Unit::TestCase
|
|
192
192
|
assert_instance_of Needle::Container, container.test2
|
193
193
|
end
|
194
194
|
|
195
|
+
def test_namespace_define
|
196
|
+
container = Needle::Container.new
|
197
|
+
container.namespace_define( :test, :pipeline=>[] ) do |b|
|
198
|
+
b.item( :pipeline=>[] ) { Hash.new }
|
199
|
+
end
|
200
|
+
assert container.has_key?( :test )
|
201
|
+
assert container.test.has_key?( :item )
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_namespace_define!
|
205
|
+
container = Needle::Container.new
|
206
|
+
container.namespace_define!( :test, :pipeline=>[] ) do
|
207
|
+
item( :pipeline=>[] ) { Hash.new }
|
208
|
+
end
|
209
|
+
assert container.has_key?( :test )
|
210
|
+
assert container.test.has_key?( :item )
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_namespace!
|
214
|
+
container = Needle::Container.new
|
215
|
+
container.namespace!( :test, :pipeline=>[] ) do
|
216
|
+
item( :pipeline=>[] ) { Hash.new }
|
217
|
+
end
|
218
|
+
assert container.has_key?( :test )
|
219
|
+
assert container.test.has_key?( :item )
|
220
|
+
end
|
221
|
+
|
195
222
|
def test_has_key
|
196
223
|
container = Needle::Container.new
|
197
224
|
|
data/test/tc_registry.rb
CHANGED
@@ -31,16 +31,33 @@ class TC_Registry < Test::Unit::TestCase
|
|
31
31
|
assert_equal 12, @registry.service_models.length
|
32
32
|
end
|
33
33
|
|
34
|
-
def
|
35
|
-
reg = Needle::Registry.
|
34
|
+
def test_define_no_options
|
35
|
+
reg = Needle::Registry.define do |b|
|
36
|
+
b.svc1 { Object.new }
|
37
|
+
end
|
38
|
+
|
39
|
+
assert_respond_to reg, :svc1
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_define_with_options
|
43
|
+
reg = Needle::Registry.define( :logs => { :device => STDOUT } ) do |b|
|
44
|
+
b.svc1 { Object.new }
|
45
|
+
end
|
46
|
+
|
47
|
+
assert_respond_to reg, :svc1
|
48
|
+
assert_equal STDOUT, reg.logs.device
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_define_no_options!
|
52
|
+
reg = Needle::Registry.define! do
|
36
53
|
svc1 { Object.new }
|
37
54
|
end
|
38
55
|
|
39
56
|
assert_respond_to reg, :svc1
|
40
57
|
end
|
41
58
|
|
42
|
-
def
|
43
|
-
reg = Needle::Registry.
|
59
|
+
def test_define_with_options!
|
60
|
+
reg = Needle::Registry.define!( :logs => { :device => STDOUT } ) do
|
44
61
|
svc1 { Object.new }
|
45
62
|
end
|
46
63
|
|
@@ -66,7 +83,7 @@ class TC_Registry < Test::Unit::TestCase
|
|
66
83
|
end
|
67
84
|
|
68
85
|
def test_fullname
|
69
|
-
|
86
|
+
assert_nil @registry.fullname
|
70
87
|
end
|
71
88
|
|
72
89
|
end
|
data/test/tc_service_point.rb
CHANGED
@@ -91,6 +91,15 @@ class TC_ServicePoint < Test::Unit::TestCase
|
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
+
def test_instance_with_explicit_pipeline_class
|
95
|
+
point =
|
96
|
+
Needle::ServicePoint.new( @container, "test", :pipeline => [ Model ] ) {
|
97
|
+
Hash.new }
|
98
|
+
|
99
|
+
inst = point.instance
|
100
|
+
assert_instance_of Hash, inst
|
101
|
+
end
|
102
|
+
|
94
103
|
def test_instance
|
95
104
|
point =
|
96
105
|
Needle::ServicePoint.new( @container, "test", :model => :mock ) {
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.1
|
|
3
3
|
specification_version: 1
|
4
4
|
name: needle
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2004-10-
|
6
|
+
version: 0.9.0
|
7
|
+
date: 2004-10-28
|
8
8
|
summary: Needle is a Dependency Injection/Inversion of Control container for Ruby. It supports both type-2 (setter) and type-3 (constructor) injection. It takes advantage of the dynamic nature of Ruby to provide a rich and flexible approach to injecting dependencies.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -30,6 +30,7 @@ files:
|
|
30
30
|
- benchmarks/interceptors.rb
|
31
31
|
- benchmarks/instantiability.rb
|
32
32
|
- benchmarks/interceptors2.rb
|
33
|
+
- doc/faq
|
33
34
|
- doc/README
|
34
35
|
- doc/LICENSE-RUBY
|
35
36
|
- doc/di-in-ruby.rdoc
|
@@ -38,6 +39,8 @@ files:
|
|
38
39
|
- doc/LICENSE-BSD
|
39
40
|
- doc/LICENSE-GPL
|
40
41
|
- doc/manual
|
42
|
+
- doc/faq/faq.yml
|
43
|
+
- doc/faq/faq.rb
|
41
44
|
- doc/manual-html/manual.css
|
42
45
|
- doc/manual-html/chapter-1.html
|
43
46
|
- doc/manual-html/chapter-2.html
|
@@ -46,6 +49,7 @@ files:
|
|
46
49
|
- doc/manual-html/chapter-5.html
|
47
50
|
- doc/manual-html/chapter-6.html
|
48
51
|
- doc/manual-html/chapter-7.html
|
52
|
+
- doc/manual-html/chapter-8.html
|
49
53
|
- doc/manual-html/index.html
|
50
54
|
- doc/images/di_classdiagram.jpg
|
51
55
|
- doc/manual/manual.css
|
@@ -58,13 +62,18 @@ files:
|
|
58
62
|
- doc/manual/manual.rb
|
59
63
|
- doc/manual/parts/02_namespaces.txt
|
60
64
|
- doc/manual/parts/01_support.txt
|
65
|
+
- doc/manual/parts/03_locator.txt
|
61
66
|
- doc/manual/parts/02_services.txt
|
67
|
+
- doc/manual/parts/04_setup.txt
|
62
68
|
- doc/manual/parts/01_alternatives.txt
|
69
|
+
- doc/manual/parts/04_overview.txt
|
63
70
|
- doc/manual/parts/01_what_is_needle.txt
|
71
|
+
- doc/manual/parts/03_overview.txt
|
64
72
|
- doc/manual/parts/02_creating.txt
|
65
73
|
- doc/manual/parts/01_license.txt
|
66
74
|
- doc/manual/parts/01_use_cases.txt
|
67
75
|
- doc/manual/parts/02_overview.txt
|
76
|
+
- doc/manual/parts/03_conventional.txt
|
68
77
|
- lib/needle.rb
|
69
78
|
- lib/needle
|
70
79
|
- lib/needle/interceptor.rb
|