needle 0.9.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/faq/faq.yml +396 -14
- data/doc/manual-html/chapter-1.html +33 -4
- data/doc/manual-html/chapter-2.html +44 -6
- data/doc/manual-html/chapter-3.html +34 -5
- data/doc/manual-html/chapter-4.html +33 -4
- data/doc/manual-html/chapter-5.html +208 -4
- data/doc/manual-html/chapter-6.html +226 -4
- data/doc/manual-html/chapter-7.html +165 -4
- data/doc/manual-html/chapter-8.html +138 -6
- data/doc/manual-html/index.html +36 -9
- data/doc/manual/manual.rb +1 -1
- data/doc/manual/manual.yml +17 -4
- data/doc/manual/page.erb +2 -1
- data/doc/manual/parts/02_namespaces.txt +11 -2
- data/doc/manual/parts/03_overview.txt +1 -1
- data/doc/manual/parts/interceptors_architecture.txt +5 -0
- data/doc/manual/parts/interceptors_attaching.txt +64 -0
- data/doc/manual/parts/interceptors_custom.txt +25 -0
- data/doc/manual/parts/interceptors_ordering.txt +13 -0
- data/doc/manual/parts/interceptors_overview.txt +5 -0
- data/doc/manual/parts/libraries_creating.txt +30 -0
- data/doc/manual/parts/libraries_overview.txt +3 -0
- data/doc/manual/parts/libraries_using.txt +31 -0
- data/doc/manual/parts/logging_configuration.txt +30 -0
- data/doc/manual/parts/logging_logfactory.txt +31 -0
- data/doc/manual/parts/logging_overview.txt +5 -0
- data/doc/manual/parts/models_models.txt +35 -0
- data/doc/manual/parts/models_overview.txt +3 -0
- data/doc/manual/parts/models_pipelines.txt +63 -0
- data/lib/needle/container.rb +52 -7
- data/lib/needle/lifecycle/initialize.rb +1 -1
- data/lib/needle/log-factory.rb +46 -8
- data/lib/needle/thread.rb +6 -0
- data/lib/needle/version.rb +2 -2
- data/test/pipeline/tc_collection.rb +1 -1
- data/test/pipeline/tc_element.rb +2 -2
- data/test/services.rb +21 -0
- data/test/tc_container.rb +18 -0
- data/test/tc_logger.rb +35 -1
- metadata +17 -2
@@ -14,8 +14,8 @@
|
|
14
14
|
</div>
|
15
15
|
</td><td valign='middle' align='right'>
|
16
16
|
<div class="info">
|
17
|
-
Needle Version: <strong>0.
|
18
|
-
Manual Last Updated: <strong>2004-
|
17
|
+
Needle Version: <strong>1.0.0</strong><br />
|
18
|
+
Manual Last Updated: <strong>2004-11-04 14:24 GMT</strong>
|
19
19
|
</div>
|
20
20
|
</td></tr>
|
21
21
|
</table>
|
@@ -105,6 +105,16 @@
|
|
105
105
|
|
106
106
|
<ol type="1">
|
107
107
|
|
108
|
+
<li><a href="chapter-5.html#s1">Overview</a></li>
|
109
|
+
|
110
|
+
<li><a href="chapter-5.html#s2">Architecture</a></li>
|
111
|
+
|
112
|
+
<li><a href="chapter-5.html#s3">Attaching</a></li>
|
113
|
+
|
114
|
+
<li><a href="chapter-5.html#s4">Ordering</a></li>
|
115
|
+
|
116
|
+
<li><a href="chapter-5.html#s5">Custom</a></li>
|
117
|
+
|
108
118
|
</ol>
|
109
119
|
</li>
|
110
120
|
|
@@ -115,6 +125,12 @@
|
|
115
125
|
|
116
126
|
<ol type="1">
|
117
127
|
|
128
|
+
<li><a href="chapter-6.html#s1">Overview</a></li>
|
129
|
+
|
130
|
+
<li><a href="chapter-6.html#s2">Pipelines</a></li>
|
131
|
+
|
132
|
+
<li><a href="chapter-6.html#s3">Models</a></li>
|
133
|
+
|
118
134
|
</ol>
|
119
135
|
</li>
|
120
136
|
|
@@ -125,25 +141,38 @@
|
|
125
141
|
|
126
142
|
<ol type="1">
|
127
143
|
|
144
|
+
<li><a href="chapter-7.html#s1">Overview</a></li>
|
145
|
+
|
146
|
+
<li><a href="chapter-7.html#s2">LogFactory</a></li>
|
147
|
+
|
148
|
+
<li><a href="chapter-7.html#s3">Configuration</a></li>
|
149
|
+
|
128
150
|
</ol>
|
129
151
|
</li>
|
130
152
|
|
131
153
|
<li>
|
132
154
|
<a href="chapter-8.html">
|
133
|
-
|
155
|
+
Service Libraries
|
134
156
|
</a>
|
135
157
|
|
136
158
|
<ol type="1">
|
137
159
|
|
160
|
+
<li><a href="chapter-8.html#s1">Overview</a></li>
|
161
|
+
|
162
|
+
<li><a href="chapter-8.html#s2">Creating Libraries</a></li>
|
163
|
+
|
164
|
+
<li><a href="chapter-8.html#s3">Using Libraries</a></li>
|
165
|
+
|
138
166
|
</ol>
|
139
167
|
</li>
|
140
168
|
|
141
169
|
</ol>
|
142
170
|
|
143
|
-
<h2>
|
171
|
+
<h2>Other Documentation</h2>
|
144
172
|
|
145
173
|
<ul>
|
146
174
|
<li><a href="http://needle.rubyforge.org/api/index.html">Needle API</a></li>
|
175
|
+
<li><a href="http://needle.rubyforge.org/faq.html">Needle FAQ</a></li>
|
147
176
|
</ul>
|
148
177
|
|
149
178
|
<h2>Tutorials</h2>
|
@@ -351,10 +380,19 @@
|
|
351
380
|
end
|
352
381
|
</pre>
|
353
382
|
|
354
|
-
<p>
|
383
|
+
<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>
|
384
|
+
|
385
|
+
<pre>
|
386
|
+
registry.namespace_define :stuff do |b|
|
387
|
+
b.foo { Bar.new }
|
388
|
+
...
|
389
|
+
end
|
390
|
+
</pre>
|
391
|
+
|
392
|
+
<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>
|
355
393
|
|
356
394
|
<pre>
|
357
|
-
registry.
|
395
|
+
registry.namespace_define! :stuff do
|
358
396
|
foo { Bar.new }
|
359
397
|
...
|
360
398
|
end
|
@@ -14,8 +14,8 @@
|
|
14
14
|
</div>
|
15
15
|
</td><td valign='middle' align='right'>
|
16
16
|
<div class="info">
|
17
|
-
Needle Version: <strong>0.
|
18
|
-
Manual Last Updated: <strong>2004-
|
17
|
+
Needle Version: <strong>1.0.0</strong><br />
|
18
|
+
Manual Last Updated: <strong>2004-11-04 14:24 GMT</strong>
|
19
19
|
</div>
|
20
20
|
</td></tr>
|
21
21
|
</table>
|
@@ -105,6 +105,16 @@
|
|
105
105
|
|
106
106
|
<ol type="1">
|
107
107
|
|
108
|
+
<li><a href="chapter-5.html#s1">Overview</a></li>
|
109
|
+
|
110
|
+
<li><a href="chapter-5.html#s2">Architecture</a></li>
|
111
|
+
|
112
|
+
<li><a href="chapter-5.html#s3">Attaching</a></li>
|
113
|
+
|
114
|
+
<li><a href="chapter-5.html#s4">Ordering</a></li>
|
115
|
+
|
116
|
+
<li><a href="chapter-5.html#s5">Custom</a></li>
|
117
|
+
|
108
118
|
</ol>
|
109
119
|
</li>
|
110
120
|
|
@@ -115,6 +125,12 @@
|
|
115
125
|
|
116
126
|
<ol type="1">
|
117
127
|
|
128
|
+
<li><a href="chapter-6.html#s1">Overview</a></li>
|
129
|
+
|
130
|
+
<li><a href="chapter-6.html#s2">Pipelines</a></li>
|
131
|
+
|
132
|
+
<li><a href="chapter-6.html#s3">Models</a></li>
|
133
|
+
|
118
134
|
</ol>
|
119
135
|
</li>
|
120
136
|
|
@@ -125,25 +141,38 @@
|
|
125
141
|
|
126
142
|
<ol type="1">
|
127
143
|
|
144
|
+
<li><a href="chapter-7.html#s1">Overview</a></li>
|
145
|
+
|
146
|
+
<li><a href="chapter-7.html#s2">LogFactory</a></li>
|
147
|
+
|
148
|
+
<li><a href="chapter-7.html#s3">Configuration</a></li>
|
149
|
+
|
128
150
|
</ol>
|
129
151
|
</li>
|
130
152
|
|
131
153
|
<li>
|
132
154
|
<a href="chapter-8.html">
|
133
|
-
|
155
|
+
Service Libraries
|
134
156
|
</a>
|
135
157
|
|
136
158
|
<ol type="1">
|
137
159
|
|
160
|
+
<li><a href="chapter-8.html#s1">Overview</a></li>
|
161
|
+
|
162
|
+
<li><a href="chapter-8.html#s2">Creating Libraries</a></li>
|
163
|
+
|
164
|
+
<li><a href="chapter-8.html#s3">Using Libraries</a></li>
|
165
|
+
|
138
166
|
</ol>
|
139
167
|
</li>
|
140
168
|
|
141
169
|
</ol>
|
142
170
|
|
143
|
-
<h2>
|
171
|
+
<h2>Other Documentation</h2>
|
144
172
|
|
145
173
|
<ul>
|
146
174
|
<li><a href="http://needle.rubyforge.org/api/index.html">Needle API</a></li>
|
175
|
+
<li><a href="http://needle.rubyforge.org/faq.html">Needle FAQ</a></li>
|
147
176
|
</ul>
|
148
177
|
|
149
178
|
<h2>Tutorials</h2>
|
@@ -188,7 +217,7 @@
|
|
188
217
|
<li><code>Application</code>. The controller that ties it all together.</li>
|
189
218
|
</ul>
|
190
219
|
|
191
|
-
<p>(Of course, a <em>real</em> online forum application would be significantly more complex, but the above components will do for our
|
220
|
+
<p>(Of course, a <em>real</em> online forum application would be significantly more complex, but the above components will do for our purposes.)</p>
|
192
221
|
|
193
222
|
<p>The dependencies between these components are:</p>
|
194
223
|
|
@@ -14,8 +14,8 @@
|
|
14
14
|
</div>
|
15
15
|
</td><td valign='middle' align='right'>
|
16
16
|
<div class="info">
|
17
|
-
Needle Version: <strong>0.
|
18
|
-
Manual Last Updated: <strong>2004-
|
17
|
+
Needle Version: <strong>1.0.0</strong><br />
|
18
|
+
Manual Last Updated: <strong>2004-11-04 14:24 GMT</strong>
|
19
19
|
</div>
|
20
20
|
</td></tr>
|
21
21
|
</table>
|
@@ -105,6 +105,16 @@
|
|
105
105
|
|
106
106
|
<ol type="1">
|
107
107
|
|
108
|
+
<li><a href="chapter-5.html#s1">Overview</a></li>
|
109
|
+
|
110
|
+
<li><a href="chapter-5.html#s2">Architecture</a></li>
|
111
|
+
|
112
|
+
<li><a href="chapter-5.html#s3">Attaching</a></li>
|
113
|
+
|
114
|
+
<li><a href="chapter-5.html#s4">Ordering</a></li>
|
115
|
+
|
116
|
+
<li><a href="chapter-5.html#s5">Custom</a></li>
|
117
|
+
|
108
118
|
</ol>
|
109
119
|
</li>
|
110
120
|
|
@@ -115,6 +125,12 @@
|
|
115
125
|
|
116
126
|
<ol type="1">
|
117
127
|
|
128
|
+
<li><a href="chapter-6.html#s1">Overview</a></li>
|
129
|
+
|
130
|
+
<li><a href="chapter-6.html#s2">Pipelines</a></li>
|
131
|
+
|
132
|
+
<li><a href="chapter-6.html#s3">Models</a></li>
|
133
|
+
|
118
134
|
</ol>
|
119
135
|
</li>
|
120
136
|
|
@@ -125,25 +141,38 @@
|
|
125
141
|
|
126
142
|
<ol type="1">
|
127
143
|
|
144
|
+
<li><a href="chapter-7.html#s1">Overview</a></li>
|
145
|
+
|
146
|
+
<li><a href="chapter-7.html#s2">LogFactory</a></li>
|
147
|
+
|
148
|
+
<li><a href="chapter-7.html#s3">Configuration</a></li>
|
149
|
+
|
128
150
|
</ol>
|
129
151
|
</li>
|
130
152
|
|
131
153
|
<li>
|
132
154
|
<a href="chapter-8.html">
|
133
|
-
|
155
|
+
Service Libraries
|
134
156
|
</a>
|
135
157
|
|
136
158
|
<ol type="1">
|
137
159
|
|
160
|
+
<li><a href="chapter-8.html#s1">Overview</a></li>
|
161
|
+
|
162
|
+
<li><a href="chapter-8.html#s2">Creating Libraries</a></li>
|
163
|
+
|
164
|
+
<li><a href="chapter-8.html#s3">Using Libraries</a></li>
|
165
|
+
|
138
166
|
</ol>
|
139
167
|
</li>
|
140
168
|
|
141
169
|
</ol>
|
142
170
|
|
143
|
-
<h2>
|
171
|
+
<h2>Other Documentation</h2>
|
144
172
|
|
145
173
|
<ul>
|
146
174
|
<li><a href="http://needle.rubyforge.org/api/index.html">Needle API</a></li>
|
175
|
+
<li><a href="http://needle.rubyforge.org/faq.html">Needle FAQ</a></li>
|
147
176
|
</ul>
|
148
177
|
|
149
178
|
<h2>Tutorials</h2>
|
@@ -14,8 +14,8 @@
|
|
14
14
|
</div>
|
15
15
|
</td><td valign='middle' align='right'>
|
16
16
|
<div class="info">
|
17
|
-
Needle Version: <strong>0.
|
18
|
-
Manual Last Updated: <strong>2004-
|
17
|
+
Needle Version: <strong>1.0.0</strong><br />
|
18
|
+
Manual Last Updated: <strong>2004-11-04 14:24 GMT</strong>
|
19
19
|
</div>
|
20
20
|
</td></tr>
|
21
21
|
</table>
|
@@ -105,6 +105,16 @@
|
|
105
105
|
</strong> <big>←</big>
|
106
106
|
<ol type="1">
|
107
107
|
|
108
|
+
<li><a href="chapter-5.html#s1">Overview</a></li>
|
109
|
+
|
110
|
+
<li><a href="chapter-5.html#s2">Architecture</a></li>
|
111
|
+
|
112
|
+
<li><a href="chapter-5.html#s3">Attaching</a></li>
|
113
|
+
|
114
|
+
<li><a href="chapter-5.html#s4">Ordering</a></li>
|
115
|
+
|
116
|
+
<li><a href="chapter-5.html#s5">Custom</a></li>
|
117
|
+
|
108
118
|
</ol>
|
109
119
|
</li>
|
110
120
|
|
@@ -115,6 +125,12 @@
|
|
115
125
|
|
116
126
|
<ol type="1">
|
117
127
|
|
128
|
+
<li><a href="chapter-6.html#s1">Overview</a></li>
|
129
|
+
|
130
|
+
<li><a href="chapter-6.html#s2">Pipelines</a></li>
|
131
|
+
|
132
|
+
<li><a href="chapter-6.html#s3">Models</a></li>
|
133
|
+
|
118
134
|
</ol>
|
119
135
|
</li>
|
120
136
|
|
@@ -125,25 +141,38 @@
|
|
125
141
|
|
126
142
|
<ol type="1">
|
127
143
|
|
144
|
+
<li><a href="chapter-7.html#s1">Overview</a></li>
|
145
|
+
|
146
|
+
<li><a href="chapter-7.html#s2">LogFactory</a></li>
|
147
|
+
|
148
|
+
<li><a href="chapter-7.html#s3">Configuration</a></li>
|
149
|
+
|
128
150
|
</ol>
|
129
151
|
</li>
|
130
152
|
|
131
153
|
<li>
|
132
154
|
<a href="chapter-8.html">
|
133
|
-
|
155
|
+
Service Libraries
|
134
156
|
</a>
|
135
157
|
|
136
158
|
<ol type="1">
|
137
159
|
|
160
|
+
<li><a href="chapter-8.html#s1">Overview</a></li>
|
161
|
+
|
162
|
+
<li><a href="chapter-8.html#s2">Creating Libraries</a></li>
|
163
|
+
|
164
|
+
<li><a href="chapter-8.html#s3">Using Libraries</a></li>
|
165
|
+
|
138
166
|
</ol>
|
139
167
|
</li>
|
140
168
|
|
141
169
|
</ol>
|
142
170
|
|
143
|
-
<h2>
|
171
|
+
<h2>Other Documentation</h2>
|
144
172
|
|
145
173
|
<ul>
|
146
174
|
<li><a href="http://needle.rubyforge.org/api/index.html">Needle API</a></li>
|
175
|
+
<li><a href="http://needle.rubyforge.org/faq.html">Needle FAQ</a></li>
|
147
176
|
</ul>
|
148
177
|
|
149
178
|
<h2>Tutorials</h2>
|
@@ -167,6 +196,181 @@
|
|
167
196
|
|
168
197
|
|
169
198
|
|
199
|
+
<h2>
|
200
|
+
<a name="s1"></a>
|
201
|
+
5.1. Overview
|
202
|
+
</h2>
|
203
|
+
|
204
|
+
|
205
|
+
|
206
|
+
<div class="section">
|
207
|
+
<p>Interceptors are objects (or blocks) that sit between a client and a service and <em>intercept</em> messages (methods) sent to the service. Each service may have many such interceptors. When control is passed to an interceptor, it may then do something before and after passing control to the next interceptor, possibly even returning instead of passing control. This allows for some simple <acronym title="Aspect-Oriented Programming">AOP</acronym>-like hooks to be placed on your services.</p>
|
208
|
+
|
209
|
+
<p>Needle comes with one interceptor, the LoggingInterceptor. This allows you to easily trace the execution of your services by logging method entry and exit, as well as any exceptions that are raised.</p>
|
210
|
+
|
211
|
+
<p>You can, of course, implement your own interceptors as well.<br />
|
212
|
+
</p>
|
213
|
+
</div>
|
214
|
+
|
215
|
+
|
216
|
+
|
217
|
+
<h2>
|
218
|
+
<a name="s2"></a>
|
219
|
+
5.2. Architecture
|
220
|
+
</h2>
|
221
|
+
|
222
|
+
|
223
|
+
|
224
|
+
<div class="section">
|
225
|
+
<p>Interceptors are implemented as proxy objects that front the requested service. Thus, if you request a service that has 3 interceptors wrapped around it, you’re really getting a proxy object back that will invoke the interceptors (in order) before the requested method of the service is invoked.</p>
|
226
|
+
|
227
|
+
<p>The interceptors themselves are attached to the service during the execution of its instantiation pipeline (see Service Models). Thus, any action in the pipeline that is situated closer to the service than the interceptor pipeline action will bypass the interceptors altogether. This allows you to attach hooks to your service that can be called without invoking the interceptors on the service.</p>
|
228
|
+
|
229
|
+
<p>Another thing to keep in mind is that the interceptors are one-to-one for each service instance. Thus, if your service is a prototype (see the Service Models chapter), you’ll have one instance of each interceptor for each instance of your service.<br />
|
230
|
+
</p>
|
231
|
+
</div>
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
<h2>
|
236
|
+
<a name="s3"></a>
|
237
|
+
5.3. Attaching
|
238
|
+
</h2>
|
239
|
+
|
240
|
+
|
241
|
+
|
242
|
+
<div class="section">
|
243
|
+
<p>There are two ways to attach interceptors to your services. The first is to implement an interceptor <em>factory</em> that returns new interceptor <em>instances</em>, and attach the factory to your service. The second is to specify a block that implements the required functionality. Both have their uses.</p>
|
244
|
+
|
245
|
+
<h3>Interceptor Factories</h3>
|
246
|
+
|
247
|
+
<p>Interceptor factories are useful in situations where you want to implement some functionality and have it apply to multiple services. Interceptors from factories are also faster (less overhead) than interceptors from blocks, and so might be appropriate where performance is an issue.</p>
|
248
|
+
|
249
|
+
<p>An example is the LoggingInterceptor that ships with Needle. Because it is functionality that could be used on any number of services, it is implemented as a factory.</p>
|
250
|
+
|
251
|
+
<p>You can attach interceptor factories to your service using the <code>#interceptor(...).with {...}</code> syntax:</p>
|
252
|
+
|
253
|
+
<pre>
|
254
|
+
reg.register( :foo ) {...}
|
255
|
+
reg.intercept( :foo ).with { MyInterceptorFactory }
|
256
|
+
</pre>
|
257
|
+
|
258
|
+
<p>Note that you could also make the interceptor factory a service:</p>
|
259
|
+
|
260
|
+
<pre>
|
261
|
+
reg.register( :foo ) {...}
|
262
|
+
reg.register( :my_interceptor ) { MyInterceptorFactory }
|
263
|
+
reg.intercept( :foo ).with { |c| c.my_interceptor }
|
264
|
+
</pre>
|
265
|
+
|
266
|
+
<p>And, to make accessing interceptor services even more convenient, you can use the <code>#with!</code> method (which executes its block within the context of the calling container):</p>
|
267
|
+
|
268
|
+
<pre>
|
269
|
+
reg.register( :foo ) {...}
|
270
|
+
reg.register( :my_interceptor ) { MyInterceptorFactory }
|
271
|
+
reg.intercept( :foo ).with! { my_interceptor }
|
272
|
+
</pre>
|
273
|
+
|
274
|
+
<h3>Blocks</h3>
|
275
|
+
|
276
|
+
<p>Sometimes creating an entire class to implement an interceptor is overkill. This is particularly the case during debugging or testing, when you might want to attach an interceptor to class to verify that a parameter passed is correct, or a return value is what you expect. To satisfy these conditions, you can using the<br />
|
277
|
+
<code>#doing</code> method. Just give it a block that accepts two parameters (the chain, and context) and you’re good to go!</p>
|
278
|
+
|
279
|
+
<pre>
|
280
|
+
reg.register( :foo ) {...}
|
281
|
+
reg.intercept( :foo ).doing { |chain,ctx| ...; chain.process_next( ctx ) }
|
282
|
+
</pre>
|
283
|
+
|
284
|
+
<p>Note that this approach is about 40% slower than using an interceptor factory, so it should not be used if performance is an issue.</p>
|
285
|
+
|
286
|
+
<h3>Options</h3>
|
287
|
+
|
288
|
+
<p>Some interceptors can accept configuration options. For example, the LoggingInterceptor allows clients to specify methods that should and shouldn’t be intercepted. Options are specified via the <code>#with_options</code> method.</p>
|
289
|
+
|
290
|
+
<pre>
|
291
|
+
reg.register( :foo ) {...}
|
292
|
+
reg.intercept( :foo ).
|
293
|
+
with { |c| c.logging_interceptor }.
|
294
|
+
with_options( :exclude => [ "method1", "method2" ] )
|
295
|
+
</pre>
|
296
|
+
|
297
|
+
<p>Options can apply to the blocks given to the <code>#doing</code> method, too. The block may access the options via the <code>#data[:options]</code> member of the context:</p>
|
298
|
+
|
299
|
+
<pre>
|
300
|
+
reg.intercept( :foo ).
|
301
|
+
doing { |ch,ctx| ...; p ctx.data[:options][:value]; ... }.
|
302
|
+
with_options( :value => "hello" )
|
303
|
+
</pre>
|
304
|
+
|
305
|
+
<p>With blocks, of course, the value of such an approach is limited.<br />
|
306
|
+
</p>
|
307
|
+
</div>
|
308
|
+
|
309
|
+
|
310
|
+
|
311
|
+
<h2>
|
312
|
+
<a name="s4"></a>
|
313
|
+
5.4. Ordering
|
314
|
+
</h2>
|
315
|
+
|
316
|
+
|
317
|
+
|
318
|
+
<div class="section">
|
319
|
+
<p>As was mentioned, a service may have multiple interceptors attached to it. By default, a method will be filtered by the interceptors in the same order that they were attached, with the first interceptor that was attached being the first one to intercept every method call.</p>
|
320
|
+
|
321
|
+
<p>You can specify a different ordering of the interceptors by giving each one a <em>priority</em>. The priority is a number, where interceptors with a higher priority sort <em>closer</em> to the service, and those with lower priorities sort <em>further</em> from the service.</p>
|
322
|
+
|
323
|
+
<p>You can specify the priority as an option when attaching an interceptor:</p>
|
324
|
+
|
325
|
+
<pre>
|
326
|
+
reg.register( :foo ) { ... }
|
327
|
+
reg.intercept( :foo ).with { Something }.with_options( :priority => 100 )
|
328
|
+
reg.intercept( :foo ).with { SomethingElse }.with_options( :priority => 50 )
|
329
|
+
</pre>
|
330
|
+
|
331
|
+
<p>Without the priorities, when a method of <code>:foo</code> was invoked, Something would be called first, and then SomethingElse. <em>With</em> the priorities (as specified), SomethingElse would be called before Something (since SomethingElse has a lower priority).<br />
|
332
|
+
</p>
|
333
|
+
</div>
|
334
|
+
|
335
|
+
|
336
|
+
|
337
|
+
<h2>
|
338
|
+
<a name="s5"></a>
|
339
|
+
5.5. Custom
|
340
|
+
</h2>
|
341
|
+
|
342
|
+
|
343
|
+
|
344
|
+
<div class="section">
|
345
|
+
<p>Creating your own interceptors is very easy. As was demonstrated earlier, you can always use blocks to implement an interceptor. However, for more complex interceptors, or for interceptors that you want to reuse across multiple services, you can also implement your own interceptor <em>factories</em>.</p>
|
346
|
+
|
347
|
+
<p>An interceptor factory can be any object, as long as it implements the method <code>#new</code> with two parameters, the <em>service point</em> (service “definition”) of the service that the interceptor will be bound to, and a hash of the options that were passed to the interceptor when it was attached to the service. This method should then return a new interceptor instance, which must implement the <code>#process</code> method. The <code>#process</code> method should accept two parameters: an object representing the <em>chain</em> of interceptors, and the invocation <em>context</em>.</p>
|
348
|
+
|
349
|
+
<pre>
|
350
|
+
class MyInterceptorFactory
|
351
|
+
def initialize( point, options )
|
352
|
+
...
|
353
|
+
end
|
354
|
+
|
355
|
+
def process( chain, context )
|
356
|
+
# context.sym : the name of the method that was invoked
|
357
|
+
# context.args : the array of arguments passed to the method
|
358
|
+
# context.block : the block passed to the method, if any
|
359
|
+
# context.data : a hash that may be used to share data between interceptors
|
360
|
+
return context.process_next( context )
|
361
|
+
end
|
362
|
+
end
|
363
|
+
</pre>
|
364
|
+
|
365
|
+
<p>Once you’ve created your factory, you can attach it to a service:</p>
|
366
|
+
|
367
|
+
<pre>
|
368
|
+
reg.intercept( :foo ).with { MyInterceptorFactory }
|
369
|
+
</pre>
|
370
|
+
</div>
|
371
|
+
|
372
|
+
|
373
|
+
|
170
374
|
|
171
375
|
</div>
|
172
376
|
|