jackbox 0.9.6.2 → 0.9.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -264,3 +264,49 @@ to re-inject them into every object they modify' do
264
264
  end
265
265
 
266
266
  end
267
+
268
+ describe 'more interesting uses' do
269
+
270
+ it 'allows the following' do
271
+
272
+ facet :PreFunction do
273
+ def pre_function
274
+ puts '++++++++++'
275
+ end
276
+ end
277
+
278
+ facet :PosFunction do
279
+ def pos_function
280
+ puts '=========='
281
+ end
282
+ end
283
+
284
+ class Model
285
+
286
+ inject PreFunction(:silence)
287
+ inject PosFunction(:silence)
288
+
289
+ def meth arg
290
+ pre_function
291
+ puts arg * arg
292
+ pos_function
293
+ end
294
+ end
295
+
296
+ obj = Model.new
297
+
298
+ $stdout.should_receive(:puts).with(4)
299
+ obj.meth( 2 )
300
+
301
+ PreFunction(:active)
302
+ PosFunction(:active)
303
+
304
+ $stdout.should_receive(:puts).with('++++++++++')
305
+ $stdout.should_receive(:puts).with(4)
306
+ $stdout.should_receive(:puts).with('==========')
307
+ obj.meth( 2 )
308
+
309
+ end
310
+
311
+
312
+ end
@@ -13,60 +13,89 @@ require "spec_helper"
13
13
 
14
14
  include Injectors
15
15
 
16
+
17
+ ####################### IMPORTANT ##############################
18
+ # NOTE: Once again, some of these examples are long on purpose.
19
+ # We are trying to show what happens to Injectors as
20
+ # a result of various lifecycle change events.
21
+ # ##############################################################
22
+
23
+
24
+
25
+ # RubyProf.start
16
26
  describe "ancestor chains" do
17
27
 
18
28
  it 'updates the ancestor chains accordingly based on: injections and ejections' do
19
-
29
+
30
+ # LifeCycle Start
31
+
20
32
  injector :Parent # capitalized method
33
+
21
34
  class Child
22
35
  include Parent()
23
36
  end
24
- Child.ancestors.to_s.should match( /Child, \(.*\|Parent\|\), Object.*BasicObject/ )
37
+ c = Child.new
38
+
39
+ # Parent is ancestor of the class and instance
40
+ Child.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )
41
+ c.singleton_class.ancestors.to_s.should match(/Child, \(\|Parent\|.*\), Object.*BasicObject/ )
42
+
43
+ # Parent is ancestor of the class and of the instance metaclass
44
+ c.enrich Parent()
45
+ c.singleton_class.ancestors.to_s.should match( /\(\|Parent\|.*\), Child, \(\|Parent\|.*\), Object.*BasicObject/ )
25
46
 
26
- c = Child.new.enrich Parent()
27
- # Parent is ancestor of the class and of the metaclass
28
- c.singleton_class.ancestors.to_s.should match( /\(.*\|Parent\|\), Child, \(.*\|Parent\|\), Object.*BasicObject/ )
29
47
 
30
- c.eject Parent()
31
48
  # Parent is ejected from the object metaclass and ancestor chain reverts back
32
- c.singleton_class.ancestors.to_s.should match( /Child, \(.*\|Parent\|\), Object.*BasicObject/ )
49
+ c.eject Parent()
50
+ c.singleton_class.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )
51
+
33
52
 
34
- Child.eject Parent()
35
53
  # Parent is ejected from the class and ancestors chain is empty
54
+ Child.eject Parent()
36
55
  Child.ancestors.to_s.should match( /Child, Object.*BasicObject/ )
37
- # cannot update empty injector
56
+
57
+
58
+ # Note: cannot update empty injector
38
59
  expect{ Child.send :update, Child.parent }.to raise_error(NoMethodError)
39
60
 
61
+
62
+ # Instance metaclass is extended with Parent twice like in the case of multiple decorators
40
63
  c.enrich Parent()
41
64
  c.enrich Parent()
42
- # object metaclass is extended with Parent twice like in the case of multiple decorators
43
- c.singleton_class.ancestors.to_s.should match( /\(.*\|Parent\|\), \(.*\|Parent\|\), Child, Object.*BasicObject/ )
65
+ c.singleton_class.ancestors.to_s.should match( /\(\|Parent\|.*\), \(\|Parent\|.*\), Child, Object.*BasicObject/ )
66
+
44
67
 
68
+ # Instance is reverted back to no Injectors
45
69
  c.eject Parent()
46
70
  c.eject Parent()
47
- # object is reverted back to no Injectors
48
71
  c.singleton_class.ancestors.to_s.should match( /Child, Object.*BasicObject/ )
49
72
 
73
+
74
+ # LyfeCycle Restart
75
+
76
+ # class is re-injected with Parent and becomes ancestor of the class and instance
50
77
  Child.inject Parent()
51
- # class is re-injected with Parent and ancestors is updated
52
- Child.ancestors.to_s.should match( /Child, \(.*\|Parent\|\), Object.*BasicObject/ )
53
- c.singleton_class.ancestors.to_s.should match( /Child, \(.*\|Parent\|\), Object.*BasicObject/ )
78
+
79
+ Child.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )
80
+ c.singleton_class.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )
54
81
 
82
+
83
+ # Parent is eject from the instance
55
84
  c.eject Parent()
56
- # class level Injector ejected from single object and ancestor for the object updated but not for class
57
85
  c.singleton_class.ancestors.to_s.should match( /Child, Object.*BasicObject/ )
58
- Child.ancestors.to_s.should match( /Child, \(.*\|Parent\|\), Object.*BasicObject/ )
86
+ Child.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )
87
+
59
88
 
89
+ # Class-level Injector update re-introduces it to objects that have ejected it locally and ancestors is updated
60
90
  Child.send :update, Parent()
61
- # class level Injector update re-introduces it to objects that have ejected it locally and ancestors is updated
62
- c.singleton_class.ancestors.to_s.should match( /Child, \(.*\|Parent\|\), Object.*BasicObject/ )
91
+ c.singleton_class.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )
63
92
 
64
93
  end
65
94
  end
66
95
 
67
- describe "the inheritance behavior of injectors" do
96
+ describe "the behavior of injectors under class inheritance" do
68
97
 
69
- example "works accross class hierarchies" do
98
+ example "working accross class hierarchies and the effects of ejection" do
70
99
 
71
100
 
72
101
  ###########################################
@@ -77,7 +106,7 @@ describe "the inheritance behavior of injectors" do
77
106
  class C
78
107
  end
79
108
  C.inject j { # #foo pre-defined at time of injection
80
- def foo
109
+ def m1
81
110
  'foo'
82
111
  end
83
112
  }
@@ -87,167 +116,177 @@ describe "the inheritance behavior of injectors" do
87
116
  injector :k
88
117
 
89
118
  C.inject k { # #faa pre-defined at injection
90
- def faa
119
+ def m2
91
120
  'faa'
92
121
  end
93
122
  }
94
- C.injectors.sym_list.should == [:j, :k]
95
- C.new.injectors.sym_list.should == [:j, :k]
123
+ C.injectors.sym_list.should == [:k, :j]
124
+ C.new.injectors.sym_list.should == [:k, :j]
96
125
 
97
- C.new.foo.should == 'foo'
98
- C.new.faa.should == 'faa'
126
+ C.new.m1.should == 'foo'
127
+ C.new.m2.should == 'faa'
99
128
  c = C.new
100
129
 
101
130
 
131
+ ########################################
102
132
  # D inherits from C
103
-
133
+ ########################################
104
134
  class D < C # methods are inherited from j and k
105
135
  end
106
- C.injectors.sym_list.should == [:j, :k]
107
- C.new.injectors.sym_list.should == [:j, :k]
136
+ C.injectors.sym_list.should == [:k, :j]
137
+ C.new.injectors.sym_list.should == [:k, :j]
108
138
  D.injectors.sym_list.should == []
109
139
  D.new.injectors.sym_list.should == []
110
140
 
111
141
  # New Objects
112
- C.new.foo.should == 'foo'
113
- C.new.faa.should == 'faa'
114
- D.new.foo.should == 'foo'
115
- D.new.faa.should == 'faa'
142
+ C.new.m1.should == 'foo'
143
+ C.new.m2.should == 'faa'
144
+ D.new.m1.should == 'foo'
145
+ D.new.m2.should == 'faa'
116
146
  # Existing Objects
117
147
  d = D.new
118
- c.foo.should == 'foo'
119
- c.faa.should == 'faa'
148
+ c.m1.should == 'foo'
149
+ c.m2.should == 'faa'
120
150
 
121
151
 
152
+ ########################################
122
153
  # inject D and override C
123
-
154
+ ########################################
124
155
  D.inject j { # new version of j pre-defined at injection
125
- def foo
156
+ def m1
126
157
  'foooo'
127
158
  end
128
159
  }
129
- C.injectors.sym_list.should == [:j, :k]
130
- C.new.injectors.sym_list.should == [:j, :k]
160
+ C.injectors.sym_list.should == [:k, :j]
161
+ C.new.injectors.sym_list.should == [:k, :j]
131
162
  D.injectors.sym_list.should == [:j]
132
163
  D.new.injectors.sym_list.should == [:j]
133
164
 
134
165
  # New Objects
135
- D.new.foo.should == 'foooo' # new version of #foo
166
+ D.new.m1.should == 'foooo' # new version of #foo
136
167
  # still the same
137
- D.new.faa.should == 'faa'
138
- C.new.foo.should == 'foo'
139
- C.new.faa.should == 'faa'
168
+ D.new.m2.should == 'faa'
169
+ C.new.m1.should == 'foo'
170
+ C.new.m2.should == 'faa'
140
171
  # Existing Objects
141
- c.foo.should == 'foo'
142
- c.faa.should == 'faa'
143
- d.foo.should == 'foooo'
144
- d.faa.should == 'faa'
172
+ c.m1.should == 'foo'
173
+ c.m2.should == 'faa'
174
+ d.m1.should == 'foooo'
175
+ d.m2.should == 'faa'
145
176
 
146
177
 
178
+ ########################################
147
179
  # D class overrides j
148
-
180
+ ########################################
149
181
  class D < C
150
- def foo # overrides foo from j
182
+ def m1 # overrides foo from j
151
183
  'fuu'
152
184
  end
153
185
  end
154
- C.injectors.sym_list.should == [:j, :k]
155
- C.new.injectors.sym_list.should == [:j, :k]
186
+ C.injectors.sym_list.should == [:k, :j]
187
+ C.new.injectors.sym_list.should == [:k, :j]
156
188
  D.injectors.sym_list.should == [:j]
157
189
  D.new.injectors.sym_list.should == [:j]
158
190
 
159
191
  # New Objects
160
- D.new.foo.should == 'fuu' # overrided last version from j
192
+ D.new.m1.should == 'fuu' # overrided last version from j
161
193
  # still the same
162
- D.new.faa.should == 'faa'
163
- C.new.foo.should == 'foo'
164
- C.new.faa.should == 'faa'
194
+ D.new.m2.should == 'faa'
195
+ C.new.m1.should == 'foo'
196
+ C.new.m2.should == 'faa'
165
197
  # Existing Objects
166
- c.foo.should == 'foo'
167
- c.faa.should == 'faa'
168
- d.foo.should == 'fuu' # overrided
169
- d.faa.should == 'faa'
198
+ c.m1.should == 'foo'
199
+ c.m2.should == 'faa'
200
+ d.m1.should == 'fuu' # overrided
201
+ d.m2.should == 'faa'
170
202
 
171
203
 
204
+ ########################################
172
205
  # update C and inherit into D
173
-
206
+ ########################################
174
207
  C.send :update, k { # new version of k pre-defined at update
175
- def faa # -- no other version of k in hierarchy
208
+ def m2 # -- no other version of k in hierarchy
176
209
  'faaxx'
177
210
  end
178
211
  }
179
- C.injectors.sym_list.should == [:j, :k]
180
- C.new.injectors.sym_list.should == [:j, :k]
212
+ # can also be written
213
+ # class C
214
+ # update k # providing k is in scope
215
+ # end
216
+ C.injectors.sym_list.should == [:k, :j]
217
+ C.new.injectors.sym_list.should == [:k, :j]
181
218
  D.injectors.sym_list.should == [:j]
182
219
  D.new.injectors.sym_list.should == [:j]
183
220
 
184
221
  # New Objects
185
- C.new.faa.should == 'faaxx' # new version of #faa
186
- D.new.faa.should == 'faaxx'
222
+ C.new.m2.should == 'faaxx' # new version of #faa
223
+ D.new.m2.should == 'faaxx'
187
224
  # still the same
188
- C.new.foo.should == 'foo'
189
- D.new.foo.should == 'fuu'
225
+ C.new.m1.should == 'foo'
226
+ D.new.m1.should == 'fuu'
190
227
  # Existing Objects
191
- c.foo.should == 'foo'
192
- c.faa.should == 'faaxx'
193
- d.foo.should == 'fuu'
194
- d.faa.should == 'faaxx'
228
+ c.m1.should == 'foo'
229
+ c.m2.should == 'faaxx'
230
+ d.m1.should == 'fuu'
231
+ d.m2.should == 'faaxx'
195
232
 
196
233
 
234
+ ########################################
197
235
  # E inherits from D
198
-
236
+ ########################################
199
237
  class E < D # methods are inherited from j at C, D and k update at C
200
238
  end
201
- C.injectors.sym_list.should == [:j, :k]
202
- C.new.injectors.sym_list.should == [:j, :k]
239
+ C.injectors.sym_list.should == [:k, :j]
240
+ C.new.injectors.sym_list.should == [:k, :j]
203
241
  D.injectors.sym_list.should == [:j]
204
242
  D.new.injectors.sym_list.should == [:j]
205
243
  E.injectors.sym_list.should == []
206
244
  E.new.injectors.sym_list.should == []
207
245
 
208
246
  # New Objects
209
- C.new.foo.should == 'foo'
210
- C.new.faa.should == 'faaxx'
211
- D.new.foo.should == 'fuu'
212
- D.new.faa.should == 'faaxx' # new objects pass
213
- E.new.foo.should == 'fuu'
214
- E.new.faa.should == 'faaxx'
247
+ C.new.m1.should == 'foo'
248
+ C.new.m2.should == 'faaxx'
249
+ D.new.m1.should == 'fuu'
250
+ D.new.m2.should == 'faaxx' # new objects pass
251
+ E.new.m1.should == 'fuu'
252
+ E.new.m2.should == 'faaxx'
215
253
  # Existing Objects
216
254
  e = E.new
217
- c.foo.should == 'foo'
218
- c.faa.should == 'faaxx' # existing objects pass
219
- d.foo.should == 'fuu'
220
- d.faa.should == 'faaxx'
255
+ c.m1.should == 'foo'
256
+ c.m2.should == 'faaxx' # existing objects pass
257
+ d.m1.should == 'fuu'
258
+ d.m2.should == 'faaxx'
221
259
 
222
260
 
261
+ ########################################
223
262
  # E overrides D
224
-
263
+ ########################################
225
264
  class E < D
226
- def foo # overrides #foo from j at C, D
265
+ def m1 # overrides #foo from j at C, D
227
266
  'fuuuu'
228
267
  end
229
268
  end
230
- C.injectors.sym_list.should == [:j, :k]
231
- C.new.injectors.sym_list.should == [:j, :k]
269
+ C.injectors.sym_list.should == [:k, :j]
270
+ C.new.injectors.sym_list.should == [:k, :j]
232
271
  D.injectors.sym_list.should == [:j]
233
272
  D.new.injectors.sym_list.should == [:j]
234
273
  E.injectors.sym_list.should == []
235
274
  E.new.injectors.sym_list.should == []
236
275
 
237
276
  # New Objects
238
- C.new.foo.should == 'foo'
239
- C.new.faa.should == 'faaxx'
240
- D.new.foo.should == 'fuu'
241
- D.new.faa.should == 'faaxx'
242
- E.new.foo.should == 'fuuuu'
243
- E.new.faa.should == 'faaxx'
277
+ C.new.m1.should == 'foo'
278
+ C.new.m2.should == 'faaxx'
279
+ D.new.m1.should == 'fuu'
280
+ D.new.m2.should == 'faaxx'
281
+ E.new.m1.should == 'fuuuu'
282
+ E.new.m2.should == 'faaxx'
244
283
  # Existing Objects
245
- c.foo.should == 'foo'
246
- c.faa.should == 'faaxx'
247
- d.foo.should == 'fuu'
248
- d.faa.should == 'faaxx'
249
- e.foo.should == 'fuuuu'
250
- e.faa.should == 'faaxx'
284
+ c.m1.should == 'foo'
285
+ c.m2.should == 'faaxx'
286
+ d.m1.should == 'fuu'
287
+ d.m2.should == 'faaxx'
288
+ e.m1.should == 'fuuuu'
289
+ e.m2.should == 'faaxx'
251
290
 
252
291
 
253
292
  #######################################
@@ -263,21 +302,24 @@ describe "the inheritance behavior of injectors" do
263
302
  E.injectors.sym_list.should == []
264
303
 
265
304
  # New Objects
266
- expect{ C.new.foo.should == 'foo'}.to raise_error(NoMethodError) # #foo errors out on C
267
- C.new.faa.should == 'faaxx'
268
- D.new.foo.should == 'fuu'
269
- D.new.faa.should == 'faaxx' # all else is the same...
270
- E.new.foo.should == 'fuuuu'
271
- E.new.faa.should == 'faaxx'
305
+ expect{ C.new.m1.should == 'foo'}.to raise_error(NoMethodError) # m1 errors out on C
306
+ C.new.m2.should == 'faaxx'
307
+ D.new.m1.should == 'fuu'
308
+ D.new.m2.should == 'faaxx' # all else is the same...
309
+ E.new.m1.should == 'fuuuu'
310
+ E.new.m2.should == 'faaxx'
272
311
  # Existing Objects
273
- expect{c.foo.should == 'foo'}.to raise_error(NoMethodError)
274
- c.faa.should == 'faaxx'
275
- d.foo.should == 'fuu'
276
- d.faa.should == 'faaxx'
277
- e.foo.should == 'fuuuu'
278
- e.faa.should == 'faaxx'
279
-
280
-
312
+ expect{c.m1.should == 'foo'}.to raise_error(NoMethodError) # m1 errors out on C
313
+ c.m2.should == 'faaxx'
314
+ d.m1.should == 'fuu'
315
+ d.m2.should == 'faaxx'
316
+ e.m1.should == 'fuuuu'
317
+ e.m2.should == 'faaxx'
318
+
319
+
320
+ ########################################
321
+ # more ejection
322
+ ########################################
281
323
  C.eject :k # eject the only k
282
324
 
283
325
  C.new.injectors.sym_list.should == []
@@ -288,21 +330,24 @@ describe "the inheritance behavior of injectors" do
288
330
  E.injectors.sym_list.should == []
289
331
 
290
332
  # New Objects
291
- expect{ C.new.foo.should == 'foo'}.to raise_error(NoMethodError)
292
- expect{ C.new.faa.should == 'faaxx'}.to raise_error(NoMethodError) # # faa errors out
293
- D.new.foo.should == 'fuu'
294
- expect{ D.new.faa.should == 'faaxx'}.to raise_error(NoMethodError) #faa errors out
295
- E.new.foo.should == 'fuuuu'
296
- expect{ E.new.faa.should == 'faaxx'}.to raise_error(NoMethodError) #faa was only available thru k at C
333
+ expect{ C.new.m1.should == 'foo'}.to raise_error(NoMethodError)
334
+ expect{ C.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) # # faa errors out
335
+ D.new.m1.should == 'fuu'
336
+ expect{ D.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) #faa errors out
337
+ E.new.m1.should == 'fuuuu'
338
+ expect{ E.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) #faa was only available thru k at C
297
339
  # Existing Objects
298
- expect{c.foo.should == 'foo'}.to raise_error(NoMethodError)
299
- expect{c.faa.should == 'faaxx'}.to raise_error(NoMethodError)
300
- d.foo.should == 'fuu' # same thing for pre-existing objects
301
- expect{d.faa.should == 'faaxx'}.to raise_error(NoMethodError)
302
- e.foo.should == 'fuuuu'
303
- expect{e.faa.should == 'faaxx'}.to raise_error(NoMethodError)
340
+ expect{c.m1.should == 'foo'}.to raise_error(NoMethodError)
341
+ expect{c.m2.should == 'faaxx'}.to raise_error(NoMethodError)
342
+ d.m1.should == 'fuu' # same thing for pre-existing objects
343
+ expect{d.m2.should == 'faaxx'}.to raise_error(NoMethodError)
344
+ e.m1.should == 'fuuuu'
345
+ expect{e.m2.should == 'faaxx'}.to raise_error(NoMethodError)
304
346
 
305
347
 
348
+ ########################################
349
+ # more ejection
350
+ ########################################
306
351
  D.eject :j # eject j from D: the only one remaining
307
352
  # -- everything should revert back to class level
308
353
  C.injectors.sym_list.should == []
@@ -311,241 +356,263 @@ describe "the inheritance behavior of injectors" do
311
356
  D.new.injectors.sym_list.should == []
312
357
  E.injectors.sym_list.should == []
313
358
  E.new.injectors.sym_list.should == []
359
+
314
360
  # New Objects
315
- expect{ C.new.foo.should == 'foo'}.to raise_error(NoMethodError) # no actual #foo on class
316
- expect{ C.new.faa.should == 'faaxx'}.to raise_error(NoMethodError) # ''
317
- D.new.foo.should == 'fuu' # retains overrides from D
318
- expect{ D.new.faa.should == 'faaxx'}.to raise_error(NoMethodError)
319
- E.new.foo.should == 'fuuuu' # retains overrides from E
320
- expect{ E.new.faa.should == 'faaxx'}.to raise_error(NoMethodError)
361
+ expect{ C.new.m1.should == 'foo'}.to raise_error(NoMethodError) # no actual #foo on class
362
+ expect{ C.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) # ''
363
+ D.new.m1.should == 'fuu' # retains overrides from D
364
+ expect{ D.new.m2.should == 'faaxx'}.to raise_error(NoMethodError)
365
+ E.new.m1.should == 'fuuuu' # retains overrides from E
366
+ expect{ E.new.m2.should == 'faaxx'}.to raise_error(NoMethodError)
321
367
  # Existing Objects
322
- expect{c.foo.should == 'foo'}.to raise_error(NoMethodError)
323
- expect{c.faa.should == 'faaxx'}.to raise_error(NoMethodError)
324
- d.foo.should == 'fuu' # same for pre-existing objects
325
- expect{d.faa.should == 'faaxx'}.to raise_error(NoMethodError)
326
- e.foo.should == 'fuuuu'
327
- expect{e.faa.should == 'faaxx'}.to raise_error(NoMethodError)
368
+ expect{c.m1.should == 'foo'}.to raise_error(NoMethodError)
369
+ expect{c.m2.should == 'faaxx'}.to raise_error(NoMethodError)
370
+ d.m1.should == 'fuu' # same for pre-existing objects
371
+ expect{d.m2.should == 'faaxx'}.to raise_error(NoMethodError)
372
+ e.m1.should == 'fuuuu'
373
+ expect{e.m2.should == 'faaxx'}.to raise_error(NoMethodError)
328
374
 
329
375
  end
330
376
 
331
- end
377
+ describe 'some special cases' do
378
+
379
+ the 'behavior when re-applying a new version of same Injector further down the line' do
332
380
 
333
- describe "some special cases and circumstances" do
381
+ class C1
382
+ end
334
383
 
335
- it 'passes on this case when we apply a <blank> Injector and then define the methods on it' do
384
+ # Define a blanck Injector
336
385
 
337
- class C1
338
- end
386
+ injector :j1
339
387
 
340
- # Define a Blank Injector
341
388
 
342
- injector :multi_levelA
389
+ # Apply to hierarchy root as defined
343
390
 
344
- C1.inject multi_levelA # apply blank injector
391
+ C1.inject j1 do # apply definitions
392
+ def m1
393
+ 'm1'
394
+ end
395
+ end
396
+ C1.new.m1.should == 'm1' # call on Injector
345
397
 
346
398
 
347
- # Define function after the application
399
+ # DD inherits from CC
348
400
 
349
- multi_levelA do
350
- def m1
351
- 'm1'
352
- end
353
- end
401
+ class D1 < C1
402
+ end # call on Injector
403
+ D1.new.m1.should == 'm1'
354
404
 
355
405
 
356
- # C1 calls
406
+ # EE inherits from DD
357
407
 
358
- C1.new.m1.should == 'm1' # call
408
+ class E1 < D1
409
+ end # call on Injector
410
+ E1.new.m1.should == 'm1'
359
411
 
360
412
 
361
- # D1 inherits from C1
413
+ ############################
414
+ # Re-define methods
415
+ ############################
416
+ j1 do # NEW VERSION! because previous had an application
417
+ def m1 # -- was applied to C1 in the hierarchy
418
+ 'm1xx' # Methods only defined in the Virtual Method Cache
419
+ end
420
+ end
362
421
 
363
- class D1 < C1
364
- end
365
- D1.new.m1.should == 'm1' # inherited call
422
+ # Calls un-affected !! # have existing version
423
+
424
+ C1.new.m1.should == 'm1'
425
+ D1.new.m1.should == 'm1'
426
+ E1.new.m1.should == 'm1'
366
427
 
367
428
 
368
- # E1 inherits from D1
429
+ E1.inject j1 # apply to hierarchy on E
430
+
431
+ C1.new.m1.should == 'm1' # same
432
+ D1.new.m1.should == 'm1' # same
433
+ E1.new.m1.should == 'm1xx' # changed
369
434
 
370
- class E1 < D1
371
435
  end
372
- E1.new.m1.should == 'm1' # inherited call
373
436
 
437
+ it 'also passes on this case' do
374
438
 
375
- # Re-define Method Cache
376
- # -- previously un-applied methods
439
+ class C2
440
+ end
377
441
 
378
- multi_levelA do
379
- def m1
380
- 'm1xx'
442
+ # Define a blank Injector
443
+
444
+ injector :j2
445
+
446
+
447
+ # Apply <full> Injector definition to an ancestor
448
+
449
+ Object.inject j2 do
450
+ def m1
451
+ 'm1xx'
452
+ end
381
453
  end
382
- end
383
-
384
-
385
- # Calls are also re-defined
386
-
387
- C1.new.m1.should == 'm1xx' # call is redefined
388
- D1.new.m1.should == 'm1xx' # ''
389
- E1.new.m1.should == 'm1xx' # ''
390
454
 
391
455
 
392
- # Apply the <full> Injector onto E1
456
+ # Call on the Injector
393
457
 
394
- E1.inject multi_levelA # Attaches this version only onto E1
395
-
396
- # calls
458
+ C2.new.m1.should == 'm1xx' # call Injector
397
459
 
398
- C1.new.m1.should == 'm1xx' # => from cache
399
- D1.new.m1.should == 'm1xx' # ''
400
-
401
- E1.new.m1.should == 'm1xx' # => from applied version
402
-
403
-
404
- # Re-define cached injector methods
405
-
406
- multi_levelA do
407
- def m1
408
- '-----'
460
+
461
+ ############################
462
+ # Re-define methods
463
+ ############################
464
+
465
+ j2 do # NEW VERSION! because previous had an application
466
+ def m1 # -- was applied to Object in the hierarchy
467
+ 'm1' # Methods only defined in the Virtual Method Cache
468
+ end
409
469
  end
410
- end
411
-
412
470
 
413
- # calls
471
+ # Calls un-afffected
414
472
 
415
- C1.new.m1.should == '-----' # re-defined!!
416
- D1.new.m1.should == '-----' # ''
417
-
418
- E1.new.m1.should == 'm1xx' # NOT REDEFINED!!
419
- # -- attached with version
420
-
421
- end
473
+ C2.new.m1.should == 'm1xx' # still using the previous version --no changes
474
+
475
+
476
+ # Inherit
477
+
478
+ class D2 < C2
479
+ end
480
+ D2.new.m1.should == 'm1xx' # using previous version
481
+
482
+
483
+ # Inherit
422
484
 
423
- it 'also passes on this case' do
485
+ class E2 < D2
486
+ end
487
+ E2.new.m1.should == 'm1xx' # using previous version
488
+
489
+
490
+ ###########################
491
+ # Finally apply new version
492
+ ###########################
493
+
494
+ C2.inject j2
495
+
496
+
497
+ # Calls changed from C on up
498
+
499
+ C2.new.m1.should == 'm1'
500
+ D2.new.m1.should == 'm1'
501
+ E2.new.m1.should == 'm1' # new version of #m1
502
+
503
+
504
+ # Call on ancestor the same
505
+
506
+ Object.new.m1.should == 'm1xx' # previous version
507
+
508
+
509
+ # back to normal
510
+
511
+ Object.eject j2 # so we do no interfere with other tests!!
424
512
 
425
- class C2
426
513
  end
427
514
 
428
- # Define a blanck Injector
429
-
430
- injector :multi_levelB
431
-
515
+ it 'acts differently when using the Virtual Method Cache (VMC)' do
432
516
 
433
- # Fill-in function as you apply
434
-
435
- C2.inject multi_levelB do # apply definitions
436
- def m1
437
- 'm1'
438
- end
439
- end
440
- C2.new.m1.should == 'm1' # call on Injector
517
+ class C3
518
+ end
441
519
 
520
+ # Define a Blank Injector
442
521
 
443
- # DD inherits from CC
522
+ injector :j3
444
523
 
445
- class D2 < C2
446
- end # call on Injector
447
- D2.new.m1.should == 'm1'
448
524
 
525
+ # Apply the blank injector
449
526
 
450
- # EE inherits from DD
527
+ C3.inject j3
451
528
 
452
- class E2 < D2
453
- end # call on Injector
454
- E2.new.m1.should == 'm1'
455
529
 
456
-
457
- # Re-define methods
458
-
459
- multi_levelB do # NEW VERSION! because previous had an application
460
- def m1 # -- was applied to C2 in the hierarchy
461
- 'm1xx'
530
+ # Define function after the application
531
+
532
+ j3 do # NEW VERSION!
533
+ def m1 # -- never applied to Object in the hierarchy
534
+ 'm1' # Methods only defined in the Virtual Method Cache
535
+ end
462
536
  end
463
- end
464
537
 
465
- # Calls un-affected !! # have existing version
466
538
 
467
- C2.new.m1.should == 'm1'
468
- D2.new.m1.should == 'm1'
469
- E2.new.m1.should == 'm1'
539
+ # C3 calls
470
540
 
471
- E2.inject multi_levelB # apply to hierarchy on E
541
+ C3.new.m1.should == 'm1' # call works as normal from VMC
472
542
 
473
- C2.new.m1.should == 'm1' # same
474
- D2.new.m1.should == 'm1' # same
475
- E2.new.m1.should == 'm1xx' # changed
476
543
 
477
- end
544
+ # D3 inherits from C3
545
+
546
+ class D3 < C3
547
+ end
548
+ D3.new.m1.should == 'm1' # inherited call
478
549
 
479
- it 'also passes on this case' do
480
-
481
- class C3
482
- end
483
550
 
484
- # Define a blank Injector
485
-
486
- injector :multi_levelC
551
+ # E3 inherits from D3
487
552
 
488
-
489
- # Apply <full> Injector definition to an ancestor
490
-
491
- Object.inject multi_levelC do
492
- def m1
493
- 'm1xx'
553
+ class E3 < D3
494
554
  end
495
- end
496
-
555
+ E3.new.m1.should == 'm1' # inherited call
497
556
 
498
- # Call on the Injector
499
-
500
- C3.new.m1.should == 'm1xx' # call Injector
501
557
 
558
+ ###################################
559
+ # Re-define Virtual Method Cache
560
+ # -- previously un-applied methods
561
+ ###################################
502
562
 
503
- # Re-define a new Injector version
563
+ j3 do # NEW VERSION!
564
+ def m1 # -- never applied to Object in the hierarchy
565
+ 'm1xx' # Methods only defined in the Virtual Method Cache
566
+ end
567
+ end
504
568
 
505
- multi_levelC do
506
- def m1
507
- 'm1'
569
+
570
+ # Calls are also re-defined
571
+
572
+ C3.new.m1.should == 'm1xx' # call is redefined
573
+ D3.new.m1.should == 'm1xx' # ''
574
+ E3.new.m1.should == 'm1xx' # ''
575
+
576
+
577
+ # Apply the <full> Injector onto E3
578
+
579
+ E3.inject j3 # Attaches this version onto E only!!
580
+
581
+ # calls
582
+
583
+ C3.new.m1.should == 'm1xx' # => from cache
584
+ D3.new.m1.should == 'm1xx' # ''
585
+
586
+ E3.new.m1.should == 'm1xx' # => from applied version
587
+
588
+
589
+ ################################
590
+ # Re-define cached methods
591
+ #################################
592
+
593
+ j3 do # NEW VERSION!
594
+ def m1 # -- never applied to Object in the hierarchy
595
+ '-----' # Methods only defined in the Virtual Method Cache
596
+ end
508
597
  end
509
- end
510
-
511
- # Calls un-afffected
512
-
513
- C3.new.m1.should == 'm1xx' # still using the previous version --no changes
514
-
515
-
516
- # Inherit
517
-
518
- class D3 < C3
519
- end
520
- D3.new.m1.should == 'm1xx' # using previous version
521
-
522
598
 
523
- # Inherit
524
-
525
- class E3 < D3
526
- end
527
- E3.new.m1.should == 'm1xx' # using previous version
528
-
529
-
530
- # Finally apply new version
531
599
 
532
- C3.inject multi_levelC
533
-
534
-
535
- # Calls changed from C on up
536
-
537
- C3.new.m1.should == 'm1'
538
- D3.new.m1.should == 'm1'
539
- E3.new.m1.should == 'm1' # new version of #m1
600
+ # calls
540
601
 
541
-
542
- # Call on ancestor the same
543
-
544
- Object.new.m1.should == 'm1xx' # previous version
602
+ C3.new.m1.should == '-----' # re-defined!!
603
+ D3.new.m1.should == '-----' # ''
604
+
605
+ E3.new.m1.should == 'm1xx' # NOT REDEFINED!!
606
+ # from applied version
607
+
608
+ end
545
609
 
546
610
  end
611
+ end
612
+
613
+ describe "regular Injector internal inheritance" do
547
614
 
548
- it 'carries current methods onto sub-versions' do
615
+ it 'carries current methods onto Injector Versions/Tags' do
549
616
 
550
617
  # Define injector
551
618
 
@@ -623,6 +690,7 @@ describe "some special cases and circumstances" do
623
690
  BoomBox.new.on.should == 'Tape playing...Lets make some music'
624
691
  JukeBox.new.on.should == 'CD playing...Lets make some music'
625
692
 
693
+ #...
626
694
 
627
695
  jack :speakers
628
696
 
@@ -630,170 +698,672 @@ describe "some special cases and circumstances" do
630
698
  def sound
631
699
  super + '...boom boom boom...'
632
700
  end
633
- end
701
+ end
702
+
634
703
  JukeBox.inject Bass
635
-
636
- #...
637
-
638
704
  JukeBox.new.on.should == 'CD playing...Lets make some music...boom boom boom...'
639
705
 
640
706
  end
641
707
 
708
+
642
709
  it 'works accross compound injectors' do
643
710
 
644
- jack :S1
711
+ jack :S1
645
712
 
646
- S1 do
647
- include jack :s2 do
648
- def s2m1
649
- end
650
- include jack :s3 do
651
- def s3m1
713
+ S1 do
714
+ include jack :s2 do
715
+ def s2m1
716
+ :s2m1
652
717
  end
653
- include jack :s4 do
654
- def s4m1
718
+ include jack :s3 do
719
+ def s3m1
720
+ :s3m1
721
+ end
722
+ include jack :s4 do
723
+ def s4m1
724
+ :s4m1
725
+ end
655
726
  end
656
727
  end
657
728
  end
658
729
  end
659
- end
660
- S1().s2.s3.s4 # injector pipeline!
661
-
662
-
663
- # Apply the injectors
664
-
665
- class CompoundContainer
666
- include S1()
667
- end
668
-
669
-
670
- # Call on the Injectors
671
-
672
- CompoundContainer.new.s2m1
673
- CompoundContainer.new.s3m1
674
- CompoundContainer.new.s4m1
730
+
731
+ S1().s2.s3.s4 # injector pipeline!
675
732
 
676
-
677
- # Add methods to the method cache of s3
678
-
679
- S1().s2.s3 do
680
- def s3m2
733
+
734
+ # Apply the injectors
735
+
736
+ class CompoundContainer
737
+ include S1()
681
738
  end
682
- end
683
- CompoundContainer.new.s3m2
684
-
685
739
 
686
- # Create a version Tag
740
+ CompoundContainer.new.s2m1.should == :s2m1
741
+ CompoundContainer.new.s3m1.should == :s3m1
742
+ CompoundContainer.new.s4m1.should == :s4m1
743
+
744
+
745
+ # Add methods to the VMC of s3
746
+
747
+ S1().s2.s3 do
748
+ def s3m2
749
+ :s3m2
750
+ end
751
+ end
752
+
753
+ CompoundContainer.new.s3m2.should == :s3m2
754
+
755
+
756
+ # Create a version Tag
757
+
758
+ AccessTag = S1()
759
+
760
+ class SecondContainer
761
+ include AccessTag
762
+ end
763
+
764
+ SecondContainer.new.s3m2.should == :s3m2
765
+
766
+ end
767
+
768
+ it 'works accross the VMC' do
769
+
770
+ expect{
771
+
772
+ injector :J1
773
+ injector :J2
774
+ injector :J3
775
+
776
+ class AA1
777
+ end
778
+ J1 do
779
+ include J2()
780
+ end
781
+ J2 do
782
+ def mJ2 # virtual cache method
783
+ :mJ2
784
+ end
785
+ end
786
+ J1 do
787
+ def mJ1 # applied method
788
+ :mJ1
789
+ end
790
+ end
791
+ class AA1
792
+ include J1()
793
+ end
794
+
795
+ AA1.new.mJ2.should == :mJ2
796
+ AA1.new.mJ1.should == :mJ1
797
+
798
+ }.not_to raise_error
687
799
 
688
- AccessTag = S1()
800
+ end
801
+
802
+ a 'different example' do
803
+
804
+ expect{
805
+
806
+ injector :K1
807
+ injector :K2
808
+ injector :K3
809
+
810
+ K1 do
811
+ include K2() do
812
+ def mj2 # applied method
813
+ :mj2
814
+ end
815
+ end
816
+ end
817
+ class AA2
818
+ include K1()
819
+ end
820
+ AA2.new.mj2.should == :mj2
821
+ K2 do
822
+ include K3() do
823
+ def mj3 # virtual cache method with another indirect
824
+ :mj3
825
+ end
826
+ end
827
+ end
828
+ AA2.new.mj3.should == :mj3
829
+
830
+ }.not_to raise_error
689
831
 
832
+ end
833
+
834
+ a 'yet different one' do
835
+
836
+ expect{
837
+
838
+ injector :M1
839
+ injector :M2
840
+ injector :M3
841
+
842
+ M1 do
843
+ include M2() do
844
+ def mk2 # applied method
845
+ :mk2
846
+ end
847
+ end
848
+ end
849
+ class AA3
850
+ include M1()
851
+ end
852
+ AA3.new.mk2.should == :mk2
853
+ M2 do
854
+ include M3()
855
+ end
856
+ M3 do
857
+ def mk3 # virtual cache method
858
+ :mk3
859
+ end
860
+ end
861
+ AA3.new.mk3.should == :mk3
862
+
863
+ }.not_to raise_error
690
864
 
691
- # Apply the Tag
865
+ end
866
+
867
+ describe 'jit inheriatnce' do
868
+
869
+ before do
870
+ injector :Tagger
871
+
872
+ end
692
873
 
693
- class SecondContainer
694
- include AccessTag
874
+ after do
875
+ Tagger(:implode)
876
+
695
877
  end
696
878
 
697
879
 
698
- # Call on tag methods
699
880
 
700
- SecondContainer.new.s3m2
701
-
702
-
703
- # Add methdos to the s2 method cache
881
+ it "follows a just-in-time inheritance policy" do
704
882
 
705
- S1().s2 do
706
- def s2m2
883
+ #
884
+ # Our Modular Closure
885
+ #
886
+ Tag1 = Tagger do
887
+ def m1
888
+ 1
889
+ end
890
+
891
+ def m2
892
+ :m2
893
+ end
894
+ end
895
+
896
+ expect(Tag1.ancestors).to eql( [Tag1] )
897
+ expect(Tagger().ancestors).to eql( [Tagger()] )
898
+
899
+
900
+ #
901
+ # Normal Injector inheritance
902
+ #
903
+ Tagger do
904
+ def other # No overrides No inheritance
905
+ 'other' # -- same ancestors as before
906
+ end # -- normal injector inheritance
907
+ end
908
+
909
+ # test it
910
+
911
+ expect(Tag1.ancestors).to eql( [Tag1] )
912
+ expect(Tagger().ancestors).to eql( [Tagger()] )
913
+
914
+ o = Object.new.extend(Tagger())
915
+
916
+ # inherited
917
+ o.m1.should == 1
918
+ o.m2.should == :m2
919
+
920
+ # current
921
+ o.other.should == 'other'
922
+
923
+
924
+ #
925
+ # JIT inheritance
926
+ #
927
+ Tag2 = Tagger do
928
+ def m1 # The :m1 override invokes JIT inheritance
929
+ super + 1 # -- Tag1 is added as ancestor
930
+ end # -- allows the use of super
931
+
932
+ def m3
933
+ 'em3'
934
+ end
935
+ end
936
+
937
+ # test it
938
+
939
+ expect(Tagger().ancestors).to eql( [Tagger(), Tag1] )
940
+ expect(Tag2.ancestors).to eql( [Tag2, Tag1] )
941
+
942
+ p = Object.new.extend(Tag2)
943
+
944
+ # JIT inherited
945
+ p.m1.should == 2
946
+
947
+ # regular inheritance
948
+ p.m2.should == :m2
949
+ p.m3.should == 'em3'
950
+ p.other.should == 'other'
951
+
952
+
953
+ #
954
+ # Under Inclusion
955
+ #
956
+ class AA6
957
+ inject Tag2
958
+ end
959
+ aa6 = AA6.new
960
+
961
+ # test it
962
+
963
+ aa6.m1.should == 2
964
+ aa6.m2.should == :m2
965
+ aa6.m3.should == 'em3'
966
+
967
+
968
+ #
969
+ # One more level: mixed level inheritance
970
+ #
971
+ Tag3 = Tagger() do
972
+ def m1
973
+ super * 2 # second override to #m1
974
+ end # -- Tag2 added as ancestor
975
+ def m3
976
+ super * 2 # first override to #m3
977
+ end
978
+ end
979
+
980
+ # test it
981
+
982
+ expect(Tagger().ancestors).to eql( [Tagger(), Tag2, Tag1] )
983
+ expect(Tag3.ancestors).to eql( [Tag3, Tag2, Tag1] )
984
+ expect(Tag2.ancestors).to eql( [Tag2, Tag1] )
985
+
986
+ class AA7
987
+ inject Tag3
988
+ end
989
+ aa7 = AA7.new
990
+
991
+ # JIT inheritance
992
+ aa7.m1.should == 4
993
+ aa7.m3.should == 'em3em3'
994
+
995
+ # regular inheritance
996
+ aa7.m2.should == :m2
997
+ aa7.other.should == 'other'
998
+
999
+
1000
+ #
1001
+ # Another version: back to basics
1002
+ #
1003
+ Tagger() do
1004
+ def m1 # another override but no call to #super
1005
+ :m1 # -- ancestor added
1006
+ end
1007
+ end
1008
+ n = Object.new.extend(Tagger())
1009
+
1010
+ # test it
1011
+
1012
+ expect(Tagger().ancestors).to eql( [Tagger(), Tag3, Tag2, Tag1] )
1013
+ expect(Tag3.ancestors).to eql( [Tag3, Tag2, Tag1] )
1014
+ expect(Tag2.ancestors).to eql( [Tag2, Tag1] )
1015
+
1016
+
1017
+ n.m1.should == :m1 # new version of #m1
1018
+
1019
+ # JIT
1020
+ n.m3.should == 'em3em3'
1021
+
1022
+ # regular
1023
+ n.m2.should == :m2
1024
+
1025
+
1026
+ #
1027
+ # Test previous versions
1028
+ #
1029
+ aa6.m1.should == 2
1030
+ aa6.m2.should == :m2
1031
+ aa6.m3.should == 'em3'
1032
+
1033
+ aa66 = AA6.new
1034
+
1035
+ aa66.m1.should == 2
1036
+ aa66.m2.should == :m2
1037
+ aa66.m3.should == 'em3'
1038
+
1039
+ aa7.m1.should == 4
1040
+ aa7.m2.should == :m2
1041
+ aa7.m3.should == 'em3em3'
1042
+
1043
+ aa77 = AA7.new
1044
+
1045
+ aa77.m1.should == 4
1046
+ aa77.m2.should == :m2
1047
+ aa77.m3.should == 'em3em3'
1048
+
1049
+
1050
+ #
1051
+ # other clients
1052
+ #
1053
+ class AA6B
1054
+ inject Tag2
1055
+ end
1056
+ aa6b = AA6B.new
1057
+
1058
+ aa6b.m1.should == 2
1059
+ aa6b.m2.should == :m2
1060
+ aa6b.m3.should == 'em3'
1061
+
1062
+ #
1063
+ # VMC (Virtual Method Cache) method
1064
+ #
1065
+ Tagger() do
1066
+ def m4
1067
+ :m4
1068
+ end
707
1069
  end
1070
+
1071
+ # test it
1072
+
1073
+ expect(Tagger().ancestors).to eql([Tagger(), Tag3, Tag2, Tag1])
1074
+ expect(Tag3.ancestors).to eql( [Tag3, Tag2, Tag1] )
1075
+ expect(Tag2.ancestors).to eql( [Tag2, Tag1] )
1076
+
1077
+ aa6b.m1.should == 2
1078
+ aa6b.m2.should == :m2
1079
+ aa6b.m3.should == 'em3'
1080
+ aa6b.m4.should == :m4 # vmc method
1081
+
1082
+
1083
+ # Total Tags
1084
+
1085
+ Tagger().tags.should == [Tag1, Tag2, Tag3]
1086
+
708
1087
  end
709
1088
 
1089
+ it "also allows further ancestor injection" do
1090
+
1091
+ Tag4 = Tagger do
1092
+ def m1
1093
+ 1
1094
+ end
1095
+ def m2
1096
+ :m2
1097
+ end
1098
+ end
710
1099
 
711
- # The current cache is available to all containers
1100
+ module Mod1
1101
+ def m1
1102
+ 'one'
1103
+ end
1104
+ end
712
1105
 
713
- CompoundContainer.new.s2m2
714
- SecondContainer.new.s2m2
715
-
716
- end
1106
+ Tag5 = Tagger(Mod1) do
1107
+
1108
+ # include Mod1 # alternatively
1109
+
1110
+ def m1
1111
+ super * 2 # invoking inheritance for Tag5 !!
1112
+ end
1113
+ def m3
1114
+ :m3
1115
+ end
1116
+ end
717
1117
 
718
- it 'pases' do
1118
+ expect(Tagger().ancestors).to eql([Tagger(), Mod1, Tag4])
1119
+ expect(Tag4.ancestors).to eql([Tag4])
1120
+ expect(Tag5.ancestors).to eql([Tag5, Mod1, Tag4])
719
1121
 
720
- injector :M1
721
- injector :M2
722
- injector :M3
1122
+ # test it
723
1123
 
724
- class AA1
725
- end
726
- M1 do
727
- include M2()
1124
+ Object.new.extend(Tag5).m1.should == 'oneone'
1125
+ Object.new.extend(Tag5).m2.should == :m2
1126
+ Object.new.extend(Tag5).m3.should == :m3
1127
+
1128
+ # other prolongation
1129
+
1130
+ Object.new.extend(Tagger(){
1131
+ def m4
1132
+ :m4
1133
+ end
1134
+ }).m4.should == :m4
1135
+
728
1136
  end
729
- M2 do
730
- def mM2
1137
+
1138
+ it 'also works like this' do
1139
+
1140
+ Tag6 = Tagger do
1141
+ def m1
1142
+ super() * 2
1143
+ end
1144
+ def m2
1145
+ :m2
1146
+ end
731
1147
  end
732
- end
733
- M1 do
734
- def mM1
1148
+
1149
+ module Mod2
1150
+ def m1
1151
+ 3
1152
+ end
735
1153
  end
1154
+
1155
+ Object.new.extend(Tagger(Mod2)).m1.should == 6
1156
+ Object.new.extend(Tagger(Mod2)).m2.should == :m2
1157
+
736
1158
  end
737
- class AA1
738
- include M1()
739
- end
740
- AA1.new.mM2
741
-
742
- end
743
-
744
- it 'passes' do
1159
+
1160
+ this "also possible" do
1161
+
1162
+ Tag7 = Tagger do
1163
+ def m1
1164
+ 1
1165
+ end
1166
+ def m2
1167
+ :m2
1168
+ end
1169
+ end
1170
+
1171
+ Tag8 = Tagger do
1172
+ def m1
1173
+ super * 2
1174
+ end
1175
+ def m3
1176
+ :m3
1177
+ end
1178
+ end
1179
+
1180
+ # test it
1181
+
1182
+ Object.new.extend(Tag8).m1.should == 2
745
1183
 
746
- injector :J1
747
- injector :J2
748
- injector :J3
749
1184
 
750
- J1 do
751
- include J2() do
752
- def mj2
753
- end
754
- end
755
- end
756
- class AA2
757
- include J1()
758
- end
759
- AA2.new.mj2
760
- J2 do
761
- include J3() do
762
- def mj3
763
- end
764
- end
1185
+ #
1186
+ # On the fly overrides
1187
+ #
1188
+ obj = Object.new.extend(
1189
+ Tagger {
1190
+ def m1
1191
+ super + 3
1192
+ end
1193
+ def m4
1194
+ :m4
1195
+ end
1196
+ })
1197
+ obj.m1.should == 5
1198
+ obj.m2.should == :m2
1199
+ obj.m3.should == :m3
1200
+ obj.m4.should == :m4
1201
+
765
1202
  end
766
- AA2.new.mj3
767
-
768
- end
769
-
770
- it 'also passes' do
771
-
772
- injector :K1
773
- injector :K2
774
- injector :K3
775
-
776
- K1 do
777
- include K2() do
778
- def mk2
1203
+
1204
+ this "one is a bit tricky" do
1205
+
1206
+ Tag9 = Tagger do
1207
+ def m1
1208
+ 1
1209
+ end
1210
+ end
1211
+
1212
+ module Mod1
1213
+ def m1
1214
+ 'one'
779
1215
  end
780
1216
  end
1217
+
1218
+ Tag10 = Tagger() do
1219
+
1220
+ include Mod1
1221
+
1222
+ def m1
1223
+ super * 2
1224
+ end
1225
+ end
1226
+
1227
+ # test it
1228
+
1229
+ Object.new.extend(Tag10).m1.should == 'oneone'
1230
+ Object.new.extend(Tagger()).m1.should == 'oneone'
1231
+
1232
+ Tag10.ancestors.should == [Tag10, Mod1, Tag9]
1233
+
781
1234
  end
782
- class AA3
783
- include K1()
1235
+
1236
+ this 'further trick' do
1237
+
1238
+ Tag11 = Tagger do
1239
+ def m1
1240
+ 1
1241
+ end
1242
+ def m2 # original definition
1243
+ 2
1244
+ end
1245
+ end
1246
+ Tag12 = Tagger do
1247
+ def m1
1248
+ 'm1'
1249
+ end # skipped #m2
1250
+ end
1251
+ Tag13 = Tagger do
1252
+ def m1
1253
+ super * 2
1254
+ end
1255
+ def m2
1256
+ super * 2 # override # m2 two levels down
1257
+ end
1258
+ end
1259
+ class AA10
1260
+ inject Tag13
1261
+ end
1262
+
1263
+ # test it
1264
+
1265
+ AA10.new.m1.should == 'm1m1'
1266
+ AA10.new.m2 == 4
1267
+
1268
+ Tag13.ancestors.should == [Tag13, Tag12, Tag11]
1269
+
784
1270
  end
785
- AA3.new.mk2
786
- K2 do
787
- include K3()
1271
+
1272
+ it 'rebases' do
1273
+
1274
+ Tag14 = Tagger do
1275
+ def m1
1276
+ 1
1277
+ end
1278
+ end
1279
+
1280
+ class AA11
1281
+ inject Tagger() do
1282
+ def m1
1283
+ super + 1
1284
+ end
1285
+ end
1286
+ end
1287
+
1288
+ # test it
1289
+
1290
+ AA11.new.m1.should == 2
1291
+
1292
+
1293
+ Tag15 = Tagger do
1294
+ def m1
1295
+ 5 # rebase m1
1296
+ end
1297
+ end
1298
+
1299
+ class BB11
1300
+ inject Tagger() do
1301
+ def m1
1302
+ super * 2 # new override
1303
+ end
1304
+ end
1305
+ end
1306
+
1307
+ # test it
1308
+
1309
+ BB11.new.m1.should == 10
1310
+
1311
+
788
1312
  end
789
- K3 do
790
- def mk3
1313
+
1314
+ it 'takes Injector Directives' do
1315
+
1316
+ Tag16 = Tagger do
1317
+ def m1
1318
+ 1
1319
+ end
1320
+ end
1321
+
1322
+ class AA12
1323
+ inject Tagger() do
1324
+ def m1
1325
+ super + 1
1326
+ end
1327
+ end
791
1328
  end
1329
+
1330
+ AA12.new.m1.should == 2
1331
+
1332
+
1333
+ Tag17 = Tagger do
1334
+ def m1
1335
+ 5 # rebase m1
1336
+ end
1337
+ end
1338
+
1339
+ class BB12
1340
+ inject Tagger() do
1341
+ def m1
1342
+ super * 2 # new override
1343
+ end
1344
+ end
1345
+ end
1346
+
1347
+ BB12.new.m1.should == 10
1348
+
1349
+ # test directives
1350
+
1351
+ Tagger(:silence)
1352
+
1353
+ AA12.new.m1.should == nil # both bases affected
1354
+ BB12.new.m1.should == nil
1355
+
1356
+ Tagger(:active)
1357
+
1358
+ AA12.new.m1.should == 2 # both bases restored
1359
+ BB12.new.m1.should == 10
1360
+
792
1361
  end
793
1362
 
794
- AA3.new.mk3
795
-
796
1363
  end
797
-
798
1364
  end
799
1365
 
1366
+ # profile = RubyProf.stop
1367
+ # RubyProf::FlatPrinter.new(profile).print(STDOUT)
1368
+ # RubyProf::GraphHtmlPrinter.new(profile).print(open('profile.html', 'w+'))
1369
+ # RubyProf::CallStackPrinter.new(profile).print(open('profile.html', 'w+'))