needle 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/manual-html/chapter-1.html +138 -78
- data/doc/manual-html/chapter-2.html +180 -99
- data/doc/manual-html/chapter-3.html +111 -75
- data/doc/manual-html/chapter-4.html +80 -48
- data/doc/manual-html/chapter-5.html +106 -56
- data/doc/manual-html/chapter-6.html +82 -34
- data/doc/manual-html/chapter-7.html +74 -38
- data/doc/manual-html/chapter-8.html +70 -41
- data/doc/manual-html/chapter-9.html +88 -63
- data/doc/manual-html/index.html +6 -6
- data/doc/manual-html/needle.png +0 -0
- data/doc/manual-html/{manual.css → stylesheets/manual.css} +83 -10
- data/doc/manual-html/stylesheets/ruby.css +17 -0
- data/doc/manual/chapter.erb +20 -0
- data/doc/manual/img/Needle.ai +0 -0
- data/doc/manual/img/needle.png +0 -0
- data/doc/manual/manual.rb +80 -5
- data/doc/manual/manual.yml +3 -3
- data/doc/manual/page.erb +1 -1
- data/doc/manual/parts/01_use_cases.txt +70 -70
- data/doc/manual/parts/02_creating.txt +19 -19
- data/doc/manual/parts/02_namespaces.txt +29 -29
- data/doc/manual/parts/02_services.txt +40 -41
- data/doc/manual/parts/03_conventional.txt +20 -20
- data/doc/manual/parts/03_locator.txt +44 -44
- data/doc/manual/parts/04_overview.txt +1 -1
- data/doc/manual/parts/04_setup.txt +32 -32
- data/doc/manual/parts/customizing_contexts.txt +14 -14
- data/doc/manual/parts/customizing_interceptors.txt +25 -25
- data/doc/manual/parts/customizing_namespaces.txt +12 -12
- data/doc/manual/parts/interceptors_attaching.txt +29 -30
- data/doc/manual/parts/interceptors_custom.txt +16 -16
- data/doc/manual/parts/interceptors_ordering.txt +5 -5
- data/doc/manual/parts/libraries_creating.txt +18 -18
- data/doc/manual/parts/libraries_using.txt +19 -19
- data/doc/manual/parts/logging_configuration.txt +13 -13
- data/doc/manual/parts/logging_logfactory.txt +21 -22
- data/doc/manual/parts/models_models.txt +8 -8
- data/doc/manual/parts/models_overview.txt +1 -1
- data/doc/manual/parts/models_pipelines.txt +22 -22
- data/doc/manual/{manual.css → stylesheets/manual.css} +83 -10
- data/doc/manual/stylesheets/ruby.css +17 -0
- data/lib/needle/definition-context.rb +3 -2
- data/lib/needle/lifecycle/proxy.rb +1 -1
- data/lib/needle/version.rb +1 -1
- metadata +94 -85
@@ -1,7 +1,7 @@
|
|
1
1
|
<html>
|
2
2
|
<head>
|
3
3
|
<title>Needle Manual :: Chapter 1: Introduction</title>
|
4
|
-
<link type="text/css" rel="stylesheet" href="manual.css" />
|
4
|
+
<link type="text/css" rel="stylesheet" href="stylesheets/manual.css" />
|
5
5
|
</head>
|
6
6
|
|
7
7
|
<body>
|
@@ -14,8 +14,8 @@
|
|
14
14
|
</div>
|
15
15
|
</td><td valign='middle' align='right'>
|
16
16
|
<div class="info">
|
17
|
-
Needle Version: <strong>1.2.
|
18
|
-
Manual Last Updated: <strong>
|
17
|
+
Needle Version: <strong>1.2.1</strong><br />
|
18
|
+
Manual Last Updated: <strong>2005-07-27 05:49 UTC</strong>
|
19
19
|
</div>
|
20
20
|
</td></tr>
|
21
21
|
</table>
|
@@ -208,7 +208,15 @@
|
|
208
208
|
|
209
209
|
<div id="content">
|
210
210
|
|
211
|
-
|
211
|
+
<div class="top"><div class="prevnext">
|
212
|
+
|
213
|
+
<a href="index.html">Up</a>
|
214
|
+
|
215
|
+
| <a href="chapter-2.html">Next (2. Registry)</a>
|
216
|
+
|
217
|
+
</div></div>
|
218
|
+
|
219
|
+
<h1>1. Introduction</h1>
|
212
220
|
|
213
221
|
|
214
222
|
|
@@ -235,143 +243,180 @@
|
|
235
243
|
<div class="section">
|
236
244
|
<p>So, what can Needle do for you? Ultimately, it can reduce the amount of code that you have to write, simplifying many common programming tasks for you. This has the two-fold benefit of both decreasing application development time, and of decreasing the effort needed to maintain your application.</p>
|
237
245
|
|
246
|
+
|
238
247
|
<p>But what, <em>specifically</em>, can Needle do for you?</p>
|
239
248
|
|
249
|
+
|
240
250
|
<p>Try these on for size:</p>
|
251
|
+
|
252
|
+
|
241
253
|
<ul>
|
242
254
|
<li><a href="#logexec">Log Method Execution</a></li>
|
243
255
|
<li><a href="#refsvc">Reference Another Service</a></li>
|
244
256
|
<li><a href="#unittest">Unit Testing</a></li>
|
245
|
-
<li><a href="#
|
257
|
+
<li><a href="#lifestyle">Lifestyle Management</a></li>
|
246
258
|
</ul>
|
247
259
|
|
260
|
+
|
248
261
|
<p>(Thanks to Howard Lewis Ship for his <a href="http://jakarta.apache.org/hivemind">HiveMind</a> documentation, from which some of the above bullet points were adapted.)</p>
|
249
262
|
|
263
|
+
|
250
264
|
<h3>Log Method Execution <a name="#logexec"></a></h3>
|
251
265
|
|
266
|
+
|
252
267
|
<p>Needle has an integrated logging framework, and the ability to log execution trace information without modifying a single line of code in your classes. This means that you can easily see what methods get called, with what arguments, and what the return values are, all without having to physically modify any of your classes.</p>
|
253
268
|
|
269
|
+
|
254
270
|
<p>Consider the following code, demonstrating how this would be done without Needle:</p>
|
255
271
|
|
256
272
|
|
257
|
-
<
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
</pre>
|
273
|
+
<div class='figure'>
|
274
|
+
<span class='caption'>Logging method execution without Needle [ruby]</span>
|
275
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="keyword">def </span><span class="method">foo</span><span class="punct">(</span> <span class="ident">arg1</span><span class="punct">,</span> <span class="ident">arg2</span> <span class="punct">)</span>
|
276
|
+
<span class="attribute">@log</span><span class="punct">.</span><span class="ident">debug</span><span class="punct">(</span> <span class="punct">"</span><span class="string">in foo with <span class="expr">#{arg1}</span> and <span class="expr">#{arg2}</span></span><span class="punct">"</span> <span class="punct">)</span> <span class="keyword">if</span> <span class="attribute">@log</span><span class="punct">.</span><span class="ident">debug?</span>
|
277
|
+
<span class="punct">...</span>
|
278
|
+
<span class="ident">result</span> <span class="punct">=</span> <span class="ident">the_result_of_the_method</span>
|
279
|
+
<span class="attribute">@log</span><span class="punct">.</span><span class="ident">debug</span><span class="punct">(</span> <span class="punct">"</span><span class="string">finishing foo with <span class="expr">#{result}</span></span><span class="punct">"</span> <span class="punct">)</span> <span class="keyword">if</span> <span class="attribute">@log</span><span class="punct">.</span><span class="ident">debug</span>
|
280
|
+
<span class="keyword">return</span> <span class="ident">result</span>
|
281
|
+
<span class="keyword">rescue</span> <span class="constant">Exception</span> <span class="punct">=></span> <span class="ident">e</span>
|
282
|
+
<span class="attribute">@log</span><span class="punct">.</span><span class="ident">debug</span><span class="punct">(</span> <span class="punct">"</span><span class="string">foo raised exception <span class="expr">#{e.message}</span> (<span class="expr">#{e.class}</span>)</span><span class="punct">"</span> <span class="punct">)</span> <span class="keyword">if</span> <span class="attribute">@log</span><span class="punct">.</span><span class="ident">debug?</span>
|
283
|
+
<span class="keyword">raise</span>
|
284
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
285
|
+
|
286
|
+
|
269
287
|
<p>Now, multiply that by the number of methods in your class… the logging messages quickly overpower the rest of the code, and detract from the flow of your program. This makes your program harder to debug, test, and maintain.</p>
|
270
288
|
|
289
|
+
|
271
290
|
<p>Now, consider the same method using Needle’s integrated logging framework…</p>
|
272
291
|
|
273
292
|
|
274
|
-
<
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
</pre>
|
293
|
+
<div class='figure'>
|
294
|
+
<span class='caption'>Logging method execution with Needle [ruby]</span>
|
295
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="keyword">def </span><span class="method">foo</span><span class="punct">(</span> <span class="ident">arg1</span><span class="punct">,</span> <span class="ident">arg2</span> <span class="punct">)</span>
|
296
|
+
<span class="punct">...</span>
|
297
|
+
<span class="keyword">return</span> <span class="ident">the_result_of_the_method</span>
|
298
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
299
|
+
|
300
|
+
|
280
301
|
<p>Then, when you define the service that you want to add the logging to:</p>
|
281
302
|
|
282
303
|
|
283
|
-
<
|
284
|
-
|
285
|
-
|
286
|
-
</pre>
|
304
|
+
<div class='figure'>
|
305
|
+
<span class='caption'>Adding the logging interceptor to a service [ruby]</span>
|
306
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span><span class="punct">.</span><span class="ident">register</span><span class="punct">(</span> <span class="symbol">:service_name_here</span> <span class="punct">)</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">reg</span><span class="punct">|</span> <span class="punct">...</span> <span class="punct">}</span>
|
307
|
+
<span class="ident">registry</span><span class="punct">.</span><span class="ident">intercept</span><span class="punct">(</span> <span class="symbol">:service_name_here</span> <span class="punct">).</span><span class="ident">with!</span> <span class="punct">{</span> <span class="ident">logging_interceptor</span> <span class="punct">}</span></pre></div></td></tr></table></div></div>
|
308
|
+
|
309
|
+
|
287
310
|
<p>That’s right. There’s no explicit logging code in there. Instead, you just tell Needle that the methods of the class should be logged, and away it goes. This has the added benefit of allowing your objects to be unit tested, without spewing log messages everywhere.</p>
|
288
311
|
|
312
|
+
|
289
313
|
<h3>Reference Another Service <a name="#refsvc"></a></h3>
|
290
314
|
|
315
|
+
|
291
316
|
<p>Invariably in a large application services will reference other services. This is typically accomplished through something like this:</p>
|
292
317
|
|
293
318
|
|
294
|
-
<
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
</pre>
|
319
|
+
<div class='figure'>
|
320
|
+
<span class='caption'>Looking up services without Needle [ruby]</span>
|
321
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="keyword">class </span><span class="class">Component</span>
|
322
|
+
<span class="punct">...</span>
|
323
|
+
<span class="keyword">def </span><span class="method">foo</span><span class="punct">(</span> <span class="ident">parms</span> <span class="punct">)</span>
|
324
|
+
<span class="attribute">@service</span> <span class="punct">||=</span> <span class="ident">lookup_service</span>
|
325
|
+
<span class="attribute">@service</span><span class="punct">.</span><span class="ident">do_something</span><span class="punct">(</span> <span class="ident">parms</span> <span class="punct">)</span>
|
326
|
+
<span class="keyword">end</span>
|
327
|
+
|
328
|
+
<span class="keyword">def </span><span class="method">lookup_service</span>
|
329
|
+
<span class="punct">...</span>
|
330
|
+
<span class="keyword">end</span>
|
331
|
+
<span class="punct">...</span>
|
332
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
333
|
+
|
334
|
+
|
308
335
|
<p>Whether the lookup is done lazily, as shown above, or when the class is first instantiated is irrelevant. The point is that you either have to implement a bunch of code to look up a service based on some criteria, or you hard code the class of the service (which creates tight coupling and makes things like unit testing harder).</p>
|
309
336
|
|
337
|
+
|
310
338
|
<p>With Needle, you just declare a setter for the service, and then tell Needle that the class depends on the other service:</p>
|
311
339
|
|
312
340
|
|
313
|
-
<
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
</pre>
|
341
|
+
<div class='figure'>
|
342
|
+
<span class='caption'>Wiring services with Needle [ruby]</span>
|
343
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="keyword">class </span><span class="class">Component</span>
|
344
|
+
<span class="ident">attr_writer</span> <span class="symbol">:service</span>
|
345
|
+
<span class="punct">...</span>
|
346
|
+
<span class="keyword">def </span><span class="method">foo</span><span class="punct">(</span> <span class="ident">parms</span> <span class="punct">)</span>
|
347
|
+
<span class="attribute">@service</span><span class="punct">.</span><span class="ident">do_something</span><span class="punct">(</span> <span class="ident">parms</span> <span class="punct">)</span>
|
348
|
+
<span class="keyword">end</span>
|
349
|
+
<span class="punct">...</span>
|
350
|
+
<span class="keyword">end</span>
|
351
|
+
|
352
|
+
<span class="ident">registry</span><span class="punct">.</span><span class="ident">register</span><span class="punct">(</span> <span class="symbol">:component</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">reg</span><span class="punct">|</span>
|
353
|
+
<span class="ident">c</span> <span class="punct">=</span> <span class="constant">Component</span><span class="punct">.</span><span class="ident">new</span>
|
354
|
+
<span class="ident">c</span><span class="punct">.</span><span class="ident">service</span> <span class="punct">=</span> <span class="ident">reg</span><span class="punct">.</span><span class="ident">some_other_service</span>
|
355
|
+
<span class="ident">c</span>
|
356
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
357
|
+
|
358
|
+
|
329
359
|
<p>Then, when your service is instantiated, Needle will automatically look for and instantiate the dependencies for you. This makes for cleaner code, and looser coupling between services.</p>
|
330
360
|
|
361
|
+
|
331
362
|
<h3>Unit Testing <a name="#unittest"></a></h3>
|
332
363
|
|
364
|
+
|
333
365
|
<p>Large applications can prove troublesome to unit test exhaustively, especially if there is any kind of tight coupling between components. Such coupling of components can make it difficult to test them separately.</p>
|
334
366
|
|
367
|
+
|
335
368
|
<p>Needle, by its very nature, encourages loose coupling of components. Also, because dependencies are never instantiated in code, but are instead accepted via setters or constructor arguments, it is trivial to replace those dependencies with mock objects at unit test time.</p>
|
336
369
|
|
370
|
+
|
337
371
|
<p>Consider this tightly coupled example:</p>
|
338
372
|
|
339
373
|
|
340
|
-
<
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
</pre>
|
374
|
+
<div class='figure'>
|
375
|
+
<span class='caption'>Tight coupling [ruby]</span>
|
376
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="keyword">def </span><span class="method">foo</span><span class="punct">(</span> <span class="ident">args</span> <span class="punct">)</span>
|
377
|
+
<span class="attribute">@some_dependency</span> <span class="punct">||=</span> <span class="constant">MyNewDependency</span><span class="punct">.</span><span class="ident">new</span>
|
378
|
+
<span class="attribute">@some_dependency</span><span class="punct">.</span><span class="ident">do_something</span><span class="punct">(</span><span class="ident">args</span><span class="punct">)</span>
|
379
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
380
|
+
|
381
|
+
|
346
382
|
<p>It is impossible to test the method <code>#foo</code> without also testing the MyNewDependency class. However, if the <code>@some_dependency</code> object is made a property that is set externally, you can replace it at test time with a blank:</p>
|
347
383
|
|
348
384
|
|
349
|
-
<
|
350
|
-
|
385
|
+
<div class='figure'>
|
386
|
+
<span class='caption'>Loose coupling [ruby]</span>
|
387
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">attr_writer</span> <span class="symbol">:some_dependency</span>
|
388
|
+
|
389
|
+
<span class="keyword">def </span><span class="method">foo</span><span class="punct">(</span> <span class="ident">args</span> <span class="punct">)</span>
|
390
|
+
<span class="attribute">@some_dependency</span><span class="punct">.</span><span class="ident">do_something</span><span class="punct">(</span> <span class="ident">args</span> <span class="punct">)</span>
|
391
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
392
|
+
|
351
393
|
|
352
|
-
def foo( args )
|
353
|
-
@some_dependency.do_something( args )
|
354
|
-
end
|
355
|
-
</pre>
|
356
394
|
<p>The unit test would become something like this:</p>
|
357
395
|
|
358
396
|
|
359
|
-
<
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
</pre>
|
366
|
-
|
397
|
+
<div class='figure'>
|
398
|
+
<span class='caption'>Unit testing with a mock object [ruby]</span>
|
399
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="keyword">def </span><span class="method">test_foo</span>
|
400
|
+
<span class="attribute">@obj</span><span class="punct">.</span><span class="ident">some_dependecy</span> <span class="punct">=</span> <span class="constant">MyMockDependency</span><span class="punct">.</span><span class="ident">new</span>
|
401
|
+
<span class="attribute">@obj</span><span class="punct">.</span><span class="ident">foo</span><span class="punct">(</span> <span class="ident">args</span> <span class="punct">)</span>
|
402
|
+
<span class="ident">assert</span> <span class="attribute">@obj</span><span class="punct">.</span><span class="ident">is_in_some_state</span>
|
403
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
404
|
+
|
405
|
+
|
406
|
+
<h3>Lifestyle Management <a name="#lifestyle"></a></h3>
|
407
|
+
|
367
408
|
|
368
409
|
<p>Singleton objects are a fact of life in complex systems. The singleton design pattern is powerful and useful. However, using the Singleton mixin, or declaring methods at the class level, can make your code difficult to unit test since the state of such objects cannot be easily reset.</p>
|
369
410
|
|
411
|
+
|
370
412
|
<p>Needle has a solution. You can tell Needle to treat a service as either a <em>prototype</em> service (meaning it will be instantiated every time you ask for it, like calling <code>#new</code>), or a <em>singleton</em> service (meaning it will only be instantiated once, and the same instance will be returned for subsequent requests).</p>
|
371
413
|
|
414
|
+
|
372
415
|
<p>Your object is still just a plain ol’ ordinary Ruby object, but Needle has effectively transformed it into a singleton. This means you can unit test it as if it were nothing special, but when it is used in your application it will act like a singleton.</p>
|
373
416
|
|
374
|
-
|
417
|
+
|
418
|
+
<p>Lifestyle management also means that you can control <em>when</em> a service is instantiated. The <em>prototype</em> and <em>singleton</em> models will always be instantiated as soon as they are requested. Sometimes, though, you don’t want that—you’d like the instantiation to be deferred as late as possible.</p>
|
419
|
+
|
375
420
|
|
376
421
|
<p>With Needle, you can indicate that a service should use deferred instantiation. This will cause the service to not actually be instantiated until a method is actually invoked on it. Using this model, you can have services depend on themselves, or other forms of cyclical dependencies.</p>
|
377
422
|
</div>
|
@@ -387,6 +432,8 @@
|
|
387
432
|
|
388
433
|
<div class="section">
|
389
434
|
<p>Needle is not the only fish in the dependency-injection pond, even when it comes to Ruby. Other containers at your disposal include:</p>
|
435
|
+
|
436
|
+
|
390
437
|
<ul>
|
391
438
|
<li><a href="http://copland.rubyforge.org">Copland</a>. Copland aims to be an “application framework”, taking something of a heavy-weight approach to DI. In so doing, it provides functionality that Needle does not, but at the cost of performance. It also uses external (YAML) configuration files. It is inspired by a Java framework (<a href="http://jakarta.apache.org/hivemind">HiveMind</a>), and so has a vaguely Java-ish flavor to it.</li>
|
392
439
|
<li><a href="http://www.picocontainer.org/Rico">Rico</a>. Rico is another project inspired by a Java project (<a href="http://www.picocontainer.org">PicoContainer</a>). It is very lean, and appears to be experimental.</li>
|
@@ -394,10 +441,13 @@
|
|
394
441
|
<li><a href="http://redshift.sourceforge.net/mindi/">MinDI</a> is a recent contender that takes a very novel approach to dependency injection. Instead of instantiating a container and adding services to it, you declare a class, mixin a DI module, and add services to the class as methods, thereby making the class the container.</li>
|
395
442
|
</ul>
|
396
443
|
|
444
|
+
|
397
445
|
<p>There is, at the time of this writing, at least one other project on RubyForge devoted to <span class="caps">DI </span>(<a href="http://rubyforge.org/projects/pith">Pith</a>), although it has no public releases yet.</p>
|
398
446
|
|
447
|
+
|
399
448
|
<p>So, which one should you choose? It comes down to an issue of personal preference, mostly, but also one of what you are wanting to accomplish. Needle excels at providing an unobtrusive, light-weight container for managing your dependencies. The cost of it being light-weight is that there is functionality it does not provide, which other containers may. If you really need that missing functionality, you are required to either implement it yourself, or select a different container.</p>
|
400
449
|
|
450
|
+
|
401
451
|
<p>For most tasks, I think you’ll find Needle more than sufficient.</p>
|
402
452
|
</div>
|
403
453
|
|
@@ -413,8 +463,10 @@
|
|
413
463
|
<div class="section">
|
414
464
|
<p>Needle is made available under either the <span class="caps">BSD</span> license, or the same license Ruby (which, by extension, also allows the <span class="caps">GPL</span> as a permissable license as well). You can view the full text of any of these licenses in the <code>doc</code> subdirectory of the Needle distrubtion. The texts of the <span class="caps">BSD</span> and <span class="caps">GPL</span> licenses are also available online: <a href="http://www.opensource.org/licenses/bsd-license.php">BSD</a> and <a href="http://www.opensource.org/licenses/gpl-license.php">GPL</a>.</p>
|
415
465
|
|
466
|
+
|
416
467
|
<p>This manual (in any form, be it source or otherwise) and the scripts and templates used to generate it, are all distributed under the <a href="http://creativecommons.org">Creative Commons</a> <a href="http://creativecommons.org/licenses/by-sa/2.0">Attribution-ShareAlike</a> license.</p>
|
417
468
|
|
469
|
+
|
418
470
|
<p>If you desire permission to use either Needle or the manual in a manner incompatible with these licenses, please contact the copyright holder (<a href="mailto:jgb3@email.byu.edu">Jamis Buck</a>) in order to negotiate a more compatible license.</p>
|
419
471
|
</div>
|
420
472
|
|
@@ -433,6 +485,14 @@
|
|
433
485
|
|
434
486
|
|
435
487
|
|
488
|
+
<div class="bottom"><div class="prevnext">
|
489
|
+
|
490
|
+
<a href="index.html">Up</a>
|
491
|
+
|
492
|
+
| <a href="chapter-2.html">Next (2. Registry)</a>
|
493
|
+
|
494
|
+
</div></div>
|
495
|
+
|
436
496
|
|
437
497
|
</div>
|
438
498
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<html>
|
2
2
|
<head>
|
3
3
|
<title>Needle Manual :: Chapter 2: Registry</title>
|
4
|
-
<link type="text/css" rel="stylesheet" href="manual.css" />
|
4
|
+
<link type="text/css" rel="stylesheet" href="stylesheets/manual.css" />
|
5
5
|
</head>
|
6
6
|
|
7
7
|
<body>
|
@@ -14,8 +14,8 @@
|
|
14
14
|
</div>
|
15
15
|
</td><td valign='middle' align='right'>
|
16
16
|
<div class="info">
|
17
|
-
Needle Version: <strong>1.2.
|
18
|
-
Manual Last Updated: <strong>
|
17
|
+
Needle Version: <strong>1.2.1</strong><br />
|
18
|
+
Manual Last Updated: <strong>2005-07-27 05:49 UTC</strong>
|
19
19
|
</div>
|
20
20
|
</td></tr>
|
21
21
|
</table>
|
@@ -208,7 +208,17 @@
|
|
208
208
|
|
209
209
|
<div id="content">
|
210
210
|
|
211
|
-
|
211
|
+
<div class="top"><div class="prevnext">
|
212
|
+
|
213
|
+
<a href="chapter-1.html">Previous (1. Introduction)</a> |
|
214
|
+
|
215
|
+
<a href="index.html">Up</a>
|
216
|
+
|
217
|
+
| <a href="chapter-3.html">Next (3. Service Locator)</a>
|
218
|
+
|
219
|
+
</div></div>
|
220
|
+
|
221
|
+
<h1>2. Registry</h1>
|
212
222
|
|
213
223
|
|
214
224
|
|
@@ -222,6 +232,7 @@
|
|
222
232
|
<div class="section">
|
223
233
|
<p>The registry is at the heart of any dependency-injected application or library. All services are registered with the registry, so that when an application needs an instance of a particular service, it may obtain that service reference by querying the registry.</p>
|
224
234
|
|
235
|
+
|
225
236
|
<p>In order to use Needle, you only really <em>need</em> to understand how to create and manipulate registry objects.</p>
|
226
237
|
</div>
|
227
238
|
|
@@ -238,41 +249,52 @@
|
|
238
249
|
<p>Creating a registry is as simple as calling <code>Needle::Registry.new</code>. This will give you a new registry object, bootstrapped to contain a few general services.</p>
|
239
250
|
|
240
251
|
|
241
|
-
<
|
242
|
-
|
252
|
+
<div class='figure'>
|
253
|
+
<span class='caption'>Creating a registry [ruby]</span>
|
254
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">require</span> <span class="punct">'</span><span class="string">needle</span><span class="punct">'</span>
|
255
|
+
|
256
|
+
<span class="ident">registry</span> <span class="punct">=</span> <span class="constant">Needle</span><span class="punct">::</span><span class="constant">Registry</span><span class="punct">.</span><span class="ident">new</span></pre></div></td></tr></table></div></div>
|
257
|
+
|
243
258
|
|
244
|
-
registry = Needle::Registry.new
|
245
|
-
</pre>
|
246
259
|
<p>Once you have the reference to the registry, you can register services with it, create new namespaces in it, and so forth.</p>
|
247
260
|
|
261
|
+
|
248
262
|
<p>Alternatively, you can pass a block to <code>#new</code>:</p>
|
249
263
|
|
250
264
|
|
251
|
-
<
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
</pre>
|
265
|
+
<div class='figure'>
|
266
|
+
<span class='caption'>Creating a registry with a block [ruby]</span>
|
267
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span> <span class="punct">=</span> <span class="constant">Needle</span><span class="punct">::</span><span class="constant">Registry</span><span class="punct">.</span><span class="ident">new</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">r</span><span class="punct">|</span>
|
268
|
+
<span class="punct">...</span>
|
269
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
270
|
+
|
271
|
+
|
256
272
|
<p>The parameter to the block will be a reference to the registry. This allows you to register services with the registry as soon as it is created.</p>
|
257
273
|
|
274
|
+
|
258
275
|
<p>Another convenience method is <code>#define!</code>:</p>
|
259
276
|
|
260
277
|
|
261
|
-
<
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
</pre>
|
278
|
+
<div class='figure'>
|
279
|
+
<span class='caption'>Creating a registry with #define! [ruby]</span>
|
280
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span> <span class="punct">=</span> <span class="constant">Needle</span><span class="punct">::</span><span class="constant">Registry</span><span class="punct">.</span><span class="ident">define!</span> <span class="keyword">do</span>
|
281
|
+
<span class="punct">...</span>
|
282
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
283
|
+
|
284
|
+
|
266
285
|
<p>This block accepts no parameters, and evaluates the block as if it were passed to <code>Registry#define!</code> (see below).</p>
|
267
286
|
|
287
|
+
|
268
288
|
<p>There can be problems with using <code>define!</code>, however, since it uses <code>instance_eval</code> to evaluate the block within the context of another object. If you find yourself running into scoping issues, you might want to consider using <code>#define</code>:</p>
|
269
289
|
|
270
290
|
|
271
|
-
<
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
</pre>
|
291
|
+
<div class='figure'>
|
292
|
+
<span class='caption'>Creating a registry with #define [ruby]</span>
|
293
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span> <span class="punct">=</span> <span class="constant">Needle</span><span class="punct">::</span><span class="constant">Registry</span><span class="punct">.</span><span class="ident">define</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">b</span><span class="punct">|</span>
|
294
|
+
<span class="punct">...</span>
|
295
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
296
|
+
|
297
|
+
|
276
298
|
<p>This block accepts a single parameter—a “builder” object to aid in registering services—and evaluates the block as if it were passed to <code>Registry#define</code> (see below).</p>
|
277
299
|
</div>
|
278
300
|
|
@@ -289,91 +311,124 @@
|
|
289
311
|
<p>Registering services with a Needle registry is very straightforward. The simplest way to do it is:</p>
|
290
312
|
|
291
313
|
|
292
|
-
<
|
293
|
-
|
294
|
-
</pre>
|
314
|
+
<div class='figure'>
|
315
|
+
<span class='caption'>Registering services [ruby]</span>
|
316
|
+
<div class='body'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span><span class="punct">.</span><span class="ident">register</span><span class="punct">(</span> <span class="symbol">:foo</span> <span class="punct">)</span> <span class="punct">{</span> <span class="constant">Bar</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">}</span></pre></div></div></div>
|
317
|
+
|
318
|
+
|
295
319
|
<p>The above will register a new service with the registry, naming it <code>:foo</code>. When <code>:foo</code> is requested from the registry, a new instance of <code>Bar</code> will be instantiated and returned.</p>
|
296
320
|
|
321
|
+
|
297
322
|
<p>You get services from the registry in either of two ways:</p>
|
298
323
|
|
299
324
|
|
300
|
-
<
|
301
|
-
|
302
|
-
|
325
|
+
<div class='figure'>
|
326
|
+
<span class='caption'>Accessing services [ruby]</span>
|
327
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="comment"># Treating the registry as a Hash</span>
|
328
|
+
<span class="ident">svc</span> <span class="punct">=</span> <span class="ident">registry</span><span class="punct">[</span><span class="symbol">:foo</span><span class="punct">]</span>
|
329
|
+
|
330
|
+
<span class="comment"># Treating the service as a property of the registry</span>
|
331
|
+
<span class="ident">svc</span> <span class="punct">=</span> <span class="ident">registry</span><span class="punct">.</span><span class="ident">foo</span></pre></div></td></tr></table></div></div>
|
332
|
+
|
303
333
|
|
304
|
-
# Treating the service as a property of the registry
|
305
|
-
svc = registry.foo
|
306
|
-
</pre>
|
307
334
|
<h3>Convenience Methods</h3>
|
308
335
|
|
336
|
+
|
309
337
|
<p>Because you will often need to register many services with a registry at once, two convenience methods have been provided to make this use case lean and mean.</p>
|
310
338
|
|
339
|
+
|
311
340
|
<p>The first is <code>define</code>. Just pass a block to define that accepts one parameter. This parameter will be a “builder” object that allows you to define services just by sending them as messages to the builder:</p>
|
312
341
|
|
313
342
|
|
314
|
-
<
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
</pre>
|
343
|
+
<div class='figure'>
|
344
|
+
<span class='caption'>Defining services [ruby]</span>
|
345
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span><span class="punct">.</span><span class="ident">define</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">b</span><span class="punct">|</span>
|
346
|
+
<span class="ident">b</span><span class="punct">.</span><span class="ident">foo</span> <span class="punct">{</span> <span class="constant">Bar</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">}</span>
|
347
|
+
<span class="ident">b</span><span class="punct">.</span><span class="ident">bar</span> <span class="punct">{</span> <span class="constant">Foo</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">}</span>
|
348
|
+
<span class="punct">...</span>
|
349
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
350
|
+
|
351
|
+
|
321
352
|
<p>Alternative, you can call <code>define!</code>, passing a block that accepts no parameters. This block will be evaluated in the “builder” object’s context, with any unrecognized method call being interpreted as a new service registration of that name:</p>
|
322
353
|
|
323
354
|
|
324
|
-
<
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
</pre>
|
355
|
+
<div class='figure'>
|
356
|
+
<span class='caption'>Defining services via #define! [ruby]</span>
|
357
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span><span class="punct">.</span><span class="ident">define!</span> <span class="keyword">do</span>
|
358
|
+
<span class="ident">foo</span> <span class="punct">{</span> <span class="constant">Bar</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">}</span>
|
359
|
+
<span class="ident">bar</span> <span class="punct">{</span> <span class="constant">Foo</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">}</span>
|
360
|
+
<span class="punct">...</span>
|
361
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
362
|
+
|
363
|
+
|
331
364
|
<p>Both of the above will register two new services with the registry, <code>:foo</code> and <code>:bar</code>.</p>
|
332
365
|
|
333
|
-
|
366
|
+
|
367
|
+
<h3>Default Lifestyle</h3>
|
368
|
+
|
334
369
|
|
335
370
|
<p>By default, a service is only instantiated once per registry. This means that (using the above example) if the service <code>:foo</code> were queried twice, the registry would return the same object for both queries:</p>
|
336
371
|
|
337
372
|
|
338
|
-
<
|
339
|
-
|
340
|
-
|
373
|
+
<div class='figure'>
|
374
|
+
<span class='caption'>Demonstrating singleton service behavior [ruby]</span>
|
375
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">svc1</span> <span class="punct">=</span> <span class="ident">registry</span><span class="punct">.</span><span class="ident">foo</span>
|
376
|
+
<span class="ident">svc2</span> <span class="punct">=</span> <span class="ident">registry</span><span class="punct">.</span><span class="ident">foo</span>
|
377
|
+
|
378
|
+
<span class="ident">p</span> <span class="ident">svc1</span><span class="punct">.</span><span class="ident">object_id</span> <span class="punct">==</span> <span class="ident">svc2</span><span class="punct">.</span><span class="ident">object_id</span> <span class="comment">#=> true</span></pre></div></td></tr></table></div></div>
|
379
|
+
|
341
380
|
|
342
|
-
p svc1.object_id == svc2.object_id #=> true
|
343
|
-
</pre>
|
344
381
|
<p>You can change this behavior, with <em>service models</em>. See the chapter on Service Models for more information.</p>
|
345
382
|
|
383
|
+
|
346
384
|
<h3>Parameterized Services</h3>
|
347
385
|
|
386
|
+
|
348
387
|
<p>Needle also supports <em>parameterized services</em>. These are services that, when requested, require contextual information to be passed as a parameter so that the service can be correctly initialized.</p>
|
349
388
|
|
389
|
+
|
350
390
|
<p>Consider the following example, in which some hypothetical <code>Printer</code> class represents any of a number of printers, based on a parameter given to its constructor.</p>
|
351
391
|
|
352
392
|
|
353
|
-
<
|
354
|
-
|
355
|
-
|
356
|
-
|
393
|
+
<div class='figure'>
|
394
|
+
<span class='caption'>Parameterized services [ruby]</span>
|
395
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span><span class="punct">.</span><span class="ident">register</span><span class="punct">(</span> <span class="symbol">:printer</span><span class="punct">,</span> <span class="symbol">:model</span> <span class="punct">=></span> <span class="symbol">:multiton</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">c</span><span class="punct">,</span><span class="ident">p</span><span class="punct">,</span><span class="ident">name</span><span class="punct">|</span>
|
396
|
+
<span class="constant">Printer</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span> <span class="ident">c</span><span class="punct">.</span><span class="ident">log_for</span><span class="punct">(</span> <span class="ident">p</span> <span class="punct">),</span> <span class="ident">name</span> <span class="punct">)</span>
|
397
|
+
<span class="keyword">end</span>
|
398
|
+
|
399
|
+
<span class="ident">mono</span> <span class="punct">=</span> <span class="ident">registry</span><span class="punct">.</span><span class="ident">printer</span><span class="punct">(</span> <span class="symbol">:monochrome</span> <span class="punct">)</span>
|
400
|
+
<span class="ident">color</span> <span class="punct">=</span> <span class="ident">registry</span><span class="punct">.</span><span class="ident">printer</span><span class="punct">(</span> <span class="symbol">:color</span> <span class="punct">)</span></pre></div></td></tr></table></div></div>
|
401
|
+
|
357
402
|
|
358
|
-
mono = registry.printer( :monochrome )
|
359
|
-
color = registry.printer( :color )
|
360
|
-
</pre>
|
361
403
|
<p>There are a few things to note about the above example:</p>
|
404
|
+
|
405
|
+
|
406
|
+
<ol>
|
407
|
+
<li>The <code>:multiton</code> model is explicitly requested. This is necessary because the default service model (<code>:singleton</code>) does not allow parameterized services. Most of the time, you’ll use the multiton service model with parameterized services, but you don’t have to. You could also use any of the prototype models as well.</li>
|
408
|
+
</ol>
|
409
|
+
|
410
|
+
|
411
|
+
<ol>
|
412
|
+
<li>The constructor block for the <code>:printer</code> service takes three parameters, <code>c</code>, <code>p</code>, and <code>name</code>. The first two parameters, <code>c</code> and <code>p</code>, represent the container and the service point, respectively. Any parameters after those two are the contextual parameters given when the service is requested. In this case, there is only one contextual parameter: the name of the printer.</li>
|
413
|
+
</ol>
|
414
|
+
|
415
|
+
|
362
416
|
<ol>
|
363
|
-
<li>
|
364
|
-
</li>
|
365
|
-
<li>The constructor block for the <code>:printer</code> service takes three parameters, <code>c</code>, <code>p</code>, and <code>name</code>. The first two parameters, <code>c</code> and <code>p</code>, represent the container and the service point, respectively. Any parameters after those two are the contextual parameters given when the service is requested. In this case, there is only one contextual parameter: the name of the printer.
|
366
|
-
</li>
|
367
|
-
<li>Notice the first parameter to the Printer constructor: <code>c.log_for(p)</code>. This is itself invoking a parameterized service, named <code>:log_for</code>, and passing <code>p</code> as the contextual information. This will return a new logger handle for the service point <code>p</code> (i.e., the current service point).
|
368
|
-
</li>
|
369
|
-
<li>See how the printer service is requested on the last two lines. In this case, the <code>#printer</code> message is sent to the registry with a single parameter. You can also request the service in two other ways:</li>
|
417
|
+
<li>Notice the first parameter to the Printer constructor: <code>c.log_for(p)</code>. This is itself invoking a parameterized service, named <code>:log_for</code>, and passing <code>p</code> as the contextual information. This will return a new logger handle for the service point <code>p</code> (i.e., the current service point).</li>
|
370
418
|
</ol>
|
371
419
|
|
372
420
|
|
373
|
-
<
|
374
|
-
|
375
|
-
|
376
|
-
|
421
|
+
<ol>
|
422
|
+
<li>See how the printer service is requested on the last two lines. In this case, the <code>#printer</code> message is sent to the registry with a single parameter. You can also request the service in two other ways:</li>
|
423
|
+
</ol>
|
424
|
+
|
425
|
+
|
426
|
+
<div class='figure'>
|
427
|
+
<span class='caption'>Accessing parameterized services [ruby]</span>
|
428
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">dot_matrix</span> <span class="punct">=</span> <span class="ident">registry</span><span class="punct">[</span> <span class="symbol">:printer</span><span class="punct">,</span> <span class="symbol">:dot_matrix</span> <span class="punct">]</span>
|
429
|
+
<span class="ident">ink_jet</span> <span class="punct">=</span> <span class="ident">registry</span><span class="punct">.</span><span class="ident">get</span><span class="punct">(</span> <span class="symbol">:printer</span><span class="punct">,</span> <span class="symbol">:ink_jet</span> <span class="punct">)</span></pre></div></td></tr></table></div></div>
|
430
|
+
|
431
|
+
|
377
432
|
<p>Choose the style that works best for you.</p>
|
378
433
|
</div>
|
379
434
|
|
@@ -388,66 +443,92 @@
|
|
388
443
|
|
389
444
|
<div class="section">
|
390
445
|
<p>Namespaces allow you to organize your services. The feature has many different applications, including:</p>
|
446
|
+
|
447
|
+
|
391
448
|
<ol>
|
392
449
|
<li>Third-parties may distribute Needle-enabled libraries without worrying about their choice of service names conflicting with the service names of their clients.</li>
|
393
450
|
<li>Developers may organize complex applications into modules, and the service definitions may be stored in the registry to reflect that organization.</li>
|
394
451
|
<li>Services deeper in the hierarchy may override services higher up.</li>
|
395
452
|
</ol>
|
396
453
|
|
454
|
+
|
397
455
|
<p>Creating a namespace is as easy as invoking the <code>#namespace</code> method of the registry (or of another namespace):</p>
|
398
456
|
|
399
457
|
|
400
|
-
<
|
401
|
-
|
402
|
-
</pre>
|
458
|
+
<div class='figure'>
|
459
|
+
<span class='caption'>Creating a namespace [ruby]</span>
|
460
|
+
<div class='body'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span><span class="punct">.</span><span class="ident">namespace</span> <span class="symbol">:stuff</span></pre></div></div></div>
|
461
|
+
|
462
|
+
|
403
463
|
<p>This would create a new namespace in the registry called <code>:stuff</code>. The application may then proceed to register services inside that namespace:</p>
|
404
464
|
|
405
465
|
|
406
|
-
<
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
</pre>
|
466
|
+
<div class='figure'>
|
467
|
+
<span class='caption'>Registering services in a namespace [ruby]</span>
|
468
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span><span class="punct">.</span><span class="ident">stuff</span><span class="punct">.</span><span class="ident">register</span><span class="punct">(</span> <span class="symbol">:foo</span> <span class="punct">)</span> <span class="punct">{</span> <span class="constant">Bar</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">}</span>
|
469
|
+
<span class="punct">...</span>
|
470
|
+
<span class="ident">svc</span> <span class="punct">=</span> <span class="ident">registry</span><span class="punct">.</span><span class="ident">stuff</span><span class="punct">.</span><span class="ident">foo</span></pre></div></td></tr></table></div></div>
|
471
|
+
|
472
|
+
|
411
473
|
<p>Here’s a tip: <em>namespaces are just a special kind of service.</em> This means that you can access namespaces in the same ways that you can access services:</p>
|
412
474
|
|
413
475
|
|
414
|
-
<
|
415
|
-
|
416
|
-
</pre>
|
476
|
+
<div class='figure'>
|
477
|
+
<span class='caption'>Accessing a namespace [ruby]</span>
|
478
|
+
<div class='body'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">svc</span> <span class="punct">=</span> <span class="ident">registry</span><span class="punct">[</span><span class="symbol">:stuff</span><span class="punct">][</span><span class="symbol">:foo</span><span class="punct">]</span></pre></div></div></div>
|
479
|
+
|
480
|
+
|
417
481
|
<h3>Convenience Methods</h3>
|
418
482
|
|
483
|
+
|
419
484
|
<p>Because it is often the case that you will be creating a namespace and then immediately registering services on it, you can pass a block to <code>namespace</code>. The block will receive a reference to the new namespace:</p>
|
420
485
|
|
421
486
|
|
422
|
-
<
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
</pre>
|
487
|
+
<div class='figure'>
|
488
|
+
<span class='caption'>More registering services in a namespace [ruby]</span>
|
489
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span><span class="punct">.</span><span class="ident">namespace</span> <span class="symbol">:stuff</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">spc</span><span class="punct">|</span>
|
490
|
+
<span class="ident">spc</span><span class="punct">.</span><span class="ident">register</span><span class="punct">(</span> <span class="symbol">:foo</span> <span class="punct">)</span> <span class="punct">{</span> <span class="constant">Bar</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">}</span>
|
491
|
+
<span class="punct">...</span>
|
492
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
493
|
+
|
494
|
+
|
428
495
|
<p>If you prefer the <code>define</code> approach to registering services, you may like <code>namespace_define</code>, which creates the new namespace and immediately calls <code>define</code> on it:</p>
|
429
496
|
|
430
497
|
|
431
|
-
<
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
</pre>
|
498
|
+
<div class='figure'>
|
499
|
+
<span class='caption'>Creating namespaces with #namespace_define [ruby]</span>
|
500
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span><span class="punct">.</span><span class="ident">namespace_define</span> <span class="symbol">:stuff</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">b</span><span class="punct">|</span>
|
501
|
+
<span class="ident">b</span><span class="punct">.</span><span class="ident">foo</span> <span class="punct">{</span> <span class="constant">Bar</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">}</span>
|
502
|
+
<span class="punct">...</span>
|
503
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
504
|
+
|
505
|
+
|
437
506
|
<p>And, to mirror the <code>namespace_define</code> method, there is also a <code>namespace_define!</code> method. This method creates a new namespace and then does a <code>define!</code> call on that namespace.</p>
|
438
507
|
|
439
508
|
|
440
|
-
<
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
</pre>
|
509
|
+
<div class='figure'>
|
510
|
+
<span class='caption'>Creating namespaces with #namespace_define! [ruby]</span>
|
511
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">registry</span><span class="punct">.</span><span class="ident">namespace_define!</span> <span class="symbol">:stuff</span> <span class="keyword">do</span>
|
512
|
+
<span class="ident">foo</span> <span class="punct">{</span> <span class="constant">Bar</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">}</span>
|
513
|
+
<span class="punct">...</span>
|
514
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
515
|
+
|
516
|
+
|
446
517
|
<p>The above code would create a new namespace called <code>:stuff</code> in the registry, and would then proceed to register a service called <code>:foo</code> in the new namespace.</p>
|
447
518
|
</div>
|
448
519
|
|
449
520
|
|
450
521
|
|
522
|
+
<div class="bottom"><div class="prevnext">
|
523
|
+
|
524
|
+
<a href="chapter-1.html">Previous (1. Introduction)</a> |
|
525
|
+
|
526
|
+
<a href="index.html">Up</a>
|
527
|
+
|
528
|
+
| <a href="chapter-3.html">Next (3. Service Locator)</a>
|
529
|
+
|
530
|
+
</div></div>
|
531
|
+
|
451
532
|
|
452
533
|
</div>
|
453
534
|
|