jackbox 0.9.6.3 → 0.9.6.6
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.
- checksums.yaml +5 -13
- data/CHANGES.txt +38 -4
- data/LICENSE.lic +0 -0
- data/README.md +568 -364
- data/lib/jackbox.rb +1 -1
- data/lib/jackbox/injectors.rb +1 -1
- data/lib/jackbox/injectors/coda.rb +2 -0
- data/lib/jackbox/injectors/prelude.rb +2 -0
- data/lib/jackbox/rake.rb +1 -1
- data/lib/jackbox/tools/prefs.rb +1 -1
- data/lib/jackbox/version.rb +1 -1
- data/spec/lib/jackbox/injector_composition_spec.rb +111 -111
- data/spec/lib/jackbox/injector_directives_spec.rb +25 -27
- data/spec/lib/jackbox/injector_inheritance_spec.rb +610 -1004
- data/spec/lib/jackbox/injector_introspection_spec.rb +265 -219
- data/spec/lib/jackbox/injector_namespacing_spec.rb +17 -17
- data/spec/lib/jackbox/injector_spec.rb +26 -0
- data/spec/lib/jackbox/injector_versioning_spec.rb +37 -37
- data/spec/lib/jackbox/jiti_rules_spec.rb +663 -0
- data/spec/lib/jackbox/patterns_spec.rb +224 -122
- data/spec/lib/jackbox/prefs_spec.rb +4 -4
- data/spec/lib/jackbox/reclassing_spec.rb +154 -406
- data/spec/lib/jackbox/vmc_spec.rb +169 -10
- data/spec/lib/jackbox_spec.rb +241 -131
- metadata +26 -26
- data/spec/lib/jackbox/examples/dx_spec.rb +0 -346
@@ -4,10 +4,10 @@ include Injectors
|
|
4
4
|
|
5
5
|
describe 'Injector Directives: ' do
|
6
6
|
|
7
|
-
describe "<
|
8
|
-
ejecting individual
|
7
|
+
describe "<trait> :implode, the entire trait and all instances eliminated. Produces different results than
|
8
|
+
ejecting individual traits, or from using <trait> :collapse and then restored using <trait> :rebuild" do
|
9
9
|
|
10
|
-
an 'example of complete
|
10
|
+
an 'example of complete trait implosion' do
|
11
11
|
|
12
12
|
class Model
|
13
13
|
def feature
|
@@ -15,7 +15,7 @@ describe 'Injector Directives: ' do
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
trait :extras do
|
19
19
|
def feature
|
20
20
|
super() + ' plus some extras'
|
21
21
|
end
|
@@ -43,20 +43,20 @@ describe 'Injector Directives: ' do
|
|
43
43
|
|
44
44
|
end
|
45
45
|
|
46
|
-
describe 'difference between
|
46
|
+
describe 'difference between trait ejection/implosion' do
|
47
47
|
|
48
48
|
the 'Injector reconstitution after ejection is possible through reinjection
|
49
|
-
but reconstitution after
|
49
|
+
but reconstitution after trait implosion is NOT AVAILABLE' do
|
50
50
|
|
51
51
|
# code defined
|
52
52
|
class Job
|
53
|
-
|
53
|
+
trait :agent do
|
54
54
|
def call
|
55
55
|
end
|
56
56
|
end
|
57
57
|
inject agent
|
58
58
|
end
|
59
|
-
Job.
|
59
|
+
Job.traits.sym_list.should == [:agent]
|
60
60
|
|
61
61
|
# normal use
|
62
62
|
expect{Job.new.call}.to_not raise_error
|
@@ -106,12 +106,12 @@ describe 'Injector Directives: ' do
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
-
describe '<
|
110
|
-
the previous except that further
|
109
|
+
describe '<trait> :collapse. Injectors can be silenced. This description produces similar results to
|
110
|
+
the previous except that further trait method calls DO NOT raise an error they just quietly return nil' do
|
111
111
|
|
112
112
|
the 'case with objects' do
|
113
113
|
|
114
|
-
|
114
|
+
trait :copiable do
|
115
115
|
def object_copy
|
116
116
|
'a dubious copy'
|
117
117
|
end
|
@@ -133,7 +133,7 @@ the previous except that further injector method calls DO NOT raise an error the
|
|
133
133
|
the 'case with classes' do
|
134
134
|
|
135
135
|
class SomeClass
|
136
|
-
|
136
|
+
trait :code do
|
137
137
|
def tester
|
138
138
|
'boo'
|
139
139
|
end
|
@@ -168,7 +168,7 @@ the previous except that further injector method calls DO NOT raise an error the
|
|
168
168
|
end
|
169
169
|
end
|
170
170
|
|
171
|
-
|
171
|
+
trait :somecode do # share member name with container
|
172
172
|
def fun
|
173
173
|
super + ' and more fun'
|
174
174
|
end
|
@@ -177,23 +177,23 @@ the previous except that further injector method calls DO NOT raise an error the
|
|
177
177
|
bc = BumperCar.new.enrich(somecode).enrich(somecode) # decorator pattern
|
178
178
|
bc.fun.should == 'this is fun and more fun and more fun'
|
179
179
|
|
180
|
-
somecode :collapse # collapse the
|
180
|
+
somecode :collapse # collapse the trait
|
181
181
|
|
182
182
|
bc.fun.should == 'this is fun' # class memeber foo intact
|
183
183
|
|
184
|
-
# eject all
|
185
|
-
bc.
|
184
|
+
# eject all traits
|
185
|
+
bc.traits.sym_list.each { |ij| bc.eject ij } # same as before
|
186
186
|
bc.fun.should == 'this is fun'
|
187
187
|
|
188
188
|
end
|
189
189
|
end
|
190
190
|
|
191
|
-
describe '<
|
191
|
+
describe '<trait> :rebuild. Quieted traits restored without having
|
192
192
|
to re-inject them into every object they modify' do
|
193
193
|
|
194
194
|
the 'case with objects' do
|
195
195
|
|
196
|
-
|
196
|
+
trait :reenforcer do
|
197
197
|
def thick_walls
|
198
198
|
'===== ====='
|
199
199
|
end
|
@@ -217,7 +217,7 @@ to re-inject them into every object they modify' do
|
|
217
217
|
the 'case with classes' do
|
218
218
|
|
219
219
|
class SomeBloatedObject
|
220
|
-
|
220
|
+
trait :ThinFunction do
|
221
221
|
def perform
|
222
222
|
'do the deed'
|
223
223
|
end
|
@@ -234,14 +234,14 @@ to re-inject them into every object they modify' do
|
|
234
234
|
|
235
235
|
end
|
236
236
|
|
237
|
-
the 'rebuild reconstructs the entire
|
237
|
+
the 'rebuild reconstructs the entire trait and all applications' do
|
238
238
|
|
239
239
|
class BumperCar
|
240
240
|
def fun
|
241
241
|
'this is fun'
|
242
242
|
end
|
243
243
|
end
|
244
|
-
|
244
|
+
trait :othercode do # share memeber name with container
|
245
245
|
def fun
|
246
246
|
super + ' and more fun'
|
247
247
|
end
|
@@ -250,7 +250,7 @@ to re-inject them into every object they modify' do
|
|
250
250
|
bc = BumperCar.new.enrich(othercode).enrich(othercode) # decorator pattern
|
251
251
|
bc.fun.should == 'this is fun and more fun and more fun'
|
252
252
|
|
253
|
-
othercode :silence # declare
|
253
|
+
othercode :silence # declare trait silence
|
254
254
|
|
255
255
|
bc.fun.should == 'this is fun' # class member un-affected
|
256
256
|
|
@@ -258,7 +258,7 @@ to re-inject them into every object they modify' do
|
|
258
258
|
bc.fun.should == 'this is fun and more fun and more fun' # restores all decorations !!!
|
259
259
|
|
260
260
|
# restore the original
|
261
|
-
bc.
|
261
|
+
bc.traits.sym_list.each { |ij| bc.eject ij } # same as before
|
262
262
|
bc.fun.should == 'this is fun'
|
263
263
|
|
264
264
|
end
|
@@ -269,13 +269,13 @@ describe 'more interesting uses' do
|
|
269
269
|
|
270
270
|
it 'allows the following' do
|
271
271
|
|
272
|
-
|
272
|
+
jack :PreFunction do
|
273
273
|
def pre_function
|
274
274
|
puts '++++++++++'
|
275
275
|
end
|
276
276
|
end
|
277
277
|
|
278
|
-
|
278
|
+
jack :PosFunction do
|
279
279
|
def pos_function
|
280
280
|
puts '=========='
|
281
281
|
end
|
@@ -307,6 +307,4 @@ describe 'more interesting uses' do
|
|
307
307
|
obj.meth( 2 )
|
308
308
|
|
309
309
|
end
|
310
|
-
|
311
|
-
|
312
310
|
end
|
@@ -22,14 +22,13 @@ include Injectors
|
|
22
22
|
|
23
23
|
|
24
24
|
|
25
|
-
# RubyProf.start
|
26
25
|
describe "ancestor chains" do
|
27
26
|
|
28
27
|
it 'updates the ancestor chains accordingly based on: injections and ejections' do
|
29
28
|
|
30
29
|
# LifeCycle Start
|
31
30
|
|
32
|
-
|
31
|
+
trait :Parent # capitalized method
|
33
32
|
|
34
33
|
class Child
|
35
34
|
include Parent()
|
@@ -55,7 +54,7 @@ describe "ancestor chains" do
|
|
55
54
|
Child.ancestors.to_s.should match( /Child, Object.*BasicObject/ )
|
56
55
|
|
57
56
|
|
58
|
-
# Note: cannot update empty
|
57
|
+
# Note: cannot update empty trait
|
59
58
|
expect{ Child.send :update, Child.parent }.to raise_error(NoMethodError)
|
60
59
|
|
61
60
|
|
@@ -93,119 +92,390 @@ describe "ancestor chains" do
|
|
93
92
|
end
|
94
93
|
end
|
95
94
|
|
96
|
-
describe "
|
95
|
+
describe "Injector Inheritance" do
|
96
|
+
|
97
|
+
it 'carries current methods onto Injector Versions/Tags' do
|
98
|
+
|
99
|
+
# Define trait
|
100
|
+
|
101
|
+
jack :bounce
|
102
|
+
|
103
|
+
bounce do
|
104
|
+
def sound
|
105
|
+
'splat splat'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# Define Tag with new methods
|
111
|
+
|
112
|
+
TagOne = bounce do
|
113
|
+
def bounce
|
114
|
+
'boing boing'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
# Apply Tag
|
120
|
+
|
121
|
+
class Ball
|
122
|
+
inject TagOne
|
123
|
+
end
|
124
|
+
Ball.new.bounce.should == 'boing boing'
|
125
|
+
|
126
|
+
|
127
|
+
class Spring
|
128
|
+
inject TagOne
|
129
|
+
end
|
130
|
+
Spring.new.bounce.should == 'boing boing'
|
131
|
+
|
132
|
+
|
133
|
+
# Inherited methods from :bounce
|
134
|
+
|
135
|
+
Ball.new.sound.should == 'splat splat'
|
136
|
+
Spring.new.sound.should == 'splat splat'
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
a "more complex example: effectively working Ruby's multiple inheritance" do
|
141
|
+
|
142
|
+
jack :player do
|
143
|
+
def sound
|
144
|
+
'Lets make some music'
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
TapePlayer = player do
|
149
|
+
def play
|
150
|
+
return 'Tape playing...' + sound()
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
CDPlayer = player do
|
155
|
+
def play
|
156
|
+
return 'CD playing...' + sound()
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class BoomBox
|
161
|
+
include TapePlayer
|
162
|
+
|
163
|
+
def on
|
164
|
+
play
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
class JukeBox < BoomBox
|
169
|
+
inject CDPlayer
|
170
|
+
end
|
171
|
+
|
172
|
+
BoomBox.new.on.should == 'Tape playing...Lets make some music'
|
173
|
+
JukeBox.new.on.should == 'CD playing...Lets make some music'
|
174
|
+
|
175
|
+
#...
|
176
|
+
|
177
|
+
jack :speakers
|
178
|
+
|
179
|
+
Bass = speakers do
|
180
|
+
def sound
|
181
|
+
super + '...boom boom boom...'
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
JukeBox.inject Bass
|
186
|
+
JukeBox.new.on.should == 'CD playing...Lets make some music...boom boom boom...'
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
it "allows a just-in-time inheritance policy" do
|
192
|
+
|
193
|
+
trait :Functionality
|
194
|
+
|
195
|
+
#
|
196
|
+
# Our Modular Closure
|
197
|
+
#
|
198
|
+
Tag1 = Functionality do
|
199
|
+
def m1
|
200
|
+
1
|
201
|
+
end
|
202
|
+
|
203
|
+
def m2
|
204
|
+
:m2
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
expect(Tag1.ancestors).to eql( [Tag1] )
|
209
|
+
expect(Functionality().ancestors).to eql( [Functionality()] )
|
210
|
+
|
211
|
+
|
212
|
+
#
|
213
|
+
# Normal Injector inheritance
|
214
|
+
#
|
215
|
+
Functionality do
|
216
|
+
def other # No overrides No inheritance
|
217
|
+
'other' # -- same ancestors as before
|
218
|
+
end # -- normal trait inheritance
|
219
|
+
end
|
220
|
+
|
221
|
+
# test it
|
222
|
+
|
223
|
+
expect(Tag1.ancestors).to eql( [Tag1] )
|
224
|
+
expect(Functionality().ancestors).to eql( [Functionality()] )
|
225
|
+
|
226
|
+
o = Object.new.extend(Functionality())
|
227
|
+
|
228
|
+
# inherited
|
229
|
+
o.m1.should == 1
|
230
|
+
o.m2.should == :m2
|
231
|
+
|
232
|
+
# current
|
233
|
+
o.other.should == 'other'
|
234
|
+
|
235
|
+
|
236
|
+
#
|
237
|
+
# JIT inheritance
|
238
|
+
#
|
239
|
+
Tag2 = Functionality do
|
240
|
+
def m1 # The :m1 override invokes JIT inheritance
|
241
|
+
super + 1 # -- Tag1 is added as ancestor
|
242
|
+
end # -- allows the use of super
|
243
|
+
|
244
|
+
def m3
|
245
|
+
'em3'
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# test it
|
250
|
+
|
251
|
+
expect(Tag2.ancestors).to eq([Tag2])
|
252
|
+
expect(Functionality().ancestors).to eq([Functionality()])
|
253
|
+
|
254
|
+
p = Object.new.extend(Tag2)
|
255
|
+
|
256
|
+
# JIT inherited
|
257
|
+
p.m1.should == 2 # using inherited function
|
258
|
+
|
259
|
+
# regular inheritance
|
260
|
+
p.m2.should == :m2
|
261
|
+
p.m3.should == 'em3'
|
262
|
+
p.other.should == 'other'
|
263
|
+
|
264
|
+
Functionality(:implode)
|
265
|
+
|
266
|
+
end
|
97
267
|
|
98
|
-
example "working accross class hierarchies and the effects of ejection" do
|
99
268
|
|
269
|
+
########################## important ############################
|
270
|
+
# For more information on JIT Inheritance (jiti), please see: #
|
271
|
+
# the accompanying spec file jiti_rules_spec.rb in the specs #
|
272
|
+
# directory. #
|
273
|
+
#################################################################
|
100
274
|
|
101
|
-
###########################################
|
102
|
-
# injection
|
103
|
-
###########################################
|
104
|
-
injector :j
|
105
275
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
276
|
+
end
|
277
|
+
|
278
|
+
describe "the behavior of traits under class inheritance" do
|
279
|
+
|
280
|
+
before do
|
281
|
+
|
282
|
+
suppress_warnings do
|
283
|
+
|
284
|
+
C = Class.new
|
285
|
+
D = Class.new(C)
|
286
|
+
E = Class.new(D)
|
287
|
+
|
288
|
+
trait :j
|
115
289
|
|
116
|
-
|
290
|
+
C.inject j { # #m1 pre-defined at time of injection
|
291
|
+
def m1
|
292
|
+
'foo'
|
293
|
+
end
|
294
|
+
}
|
117
295
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
296
|
+
trait :k
|
297
|
+
|
298
|
+
C.inject k do # #m2 pre-defined at injection
|
299
|
+
def m2
|
300
|
+
'faa'
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
125
307
|
|
126
|
-
|
127
|
-
|
308
|
+
after do
|
309
|
+
|
310
|
+
suppress_warnings do
|
311
|
+
|
312
|
+
j(:implode)
|
313
|
+
k(:implode)
|
314
|
+
|
315
|
+
C = nil
|
316
|
+
D = nil
|
317
|
+
E = nil
|
318
|
+
|
319
|
+
end
|
320
|
+
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'works on a first level' do
|
324
|
+
|
325
|
+
C.traits.sym_list.should == [:k, :j]
|
326
|
+
C.new.traits.sym_list.should == [:k, :j]
|
128
327
|
c = C.new
|
129
328
|
|
329
|
+
# New Objects
|
330
|
+
with C.new do
|
331
|
+
m1.should == 'foo'
|
332
|
+
m2.should == 'faa'
|
333
|
+
end
|
334
|
+
# Existing objects
|
335
|
+
with c do
|
336
|
+
m1.should == 'foo'
|
337
|
+
m2.should == 'faa'
|
338
|
+
end
|
339
|
+
|
340
|
+
end
|
341
|
+
|
342
|
+
example "adding another level" do
|
343
|
+
|
344
|
+
|
345
|
+
####################################
|
346
|
+
# Preamble
|
347
|
+
####################################
|
348
|
+
c = C.new # carry over from above
|
130
349
|
|
131
|
-
|
350
|
+
####################################
|
132
351
|
# D inherits from C
|
133
|
-
|
134
|
-
class D < C
|
352
|
+
####################################
|
353
|
+
class D < C # methods are inherited from j and k
|
135
354
|
end
|
136
|
-
C.injectors.sym_list.should == [:k, :j]
|
137
|
-
C.new.injectors.sym_list.should == [:k, :j]
|
138
|
-
D.injectors.sym_list.should == []
|
139
|
-
D.new.injectors.sym_list.should == []
|
140
355
|
|
356
|
+
D.traits(:all).sym_list.should == [:k, :j]
|
357
|
+
D.new.traits(:all).sym_list.should == [:k, :j]
|
358
|
+
d = D.new
|
359
|
+
|
141
360
|
# New Objects
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
# Existing
|
147
|
-
|
148
|
-
|
149
|
-
|
361
|
+
with D.new do
|
362
|
+
m1.should == 'foo'
|
363
|
+
m2.should == 'faa'
|
364
|
+
end
|
365
|
+
# Existing objects
|
366
|
+
with c, d do
|
367
|
+
m1.should == 'foo'
|
368
|
+
m2.should == 'faa'
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
150
372
|
|
373
|
+
example 'traits on second level' do
|
151
374
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
375
|
+
####################################
|
376
|
+
# Preamble
|
377
|
+
####################################
|
378
|
+
c = C.new
|
379
|
+
|
380
|
+
####################################
|
381
|
+
# inject into D overriding C
|
382
|
+
####################################
|
383
|
+
D.inject j { # new version of j pre-defined at injection
|
156
384
|
def m1
|
157
385
|
'foooo'
|
158
386
|
end
|
159
387
|
}
|
160
|
-
|
161
|
-
|
162
|
-
D.
|
163
|
-
D.new.injectors.sym_list.should == [:j]
|
388
|
+
D.traits(:all).sym_list.should == [:j, :k, :j]
|
389
|
+
D.new.traits(:all).sym_list.should == [:j, :k, :j]
|
390
|
+
d = D.new
|
164
391
|
|
165
392
|
# New Objects
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
C.new.m2.should == 'faa'
|
393
|
+
with D.new do
|
394
|
+
m1.should == 'foooo' # new version of #m1
|
395
|
+
m2.should == 'faa' # still the same
|
396
|
+
end
|
171
397
|
# Existing Objects
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
398
|
+
with c do
|
399
|
+
m1.should == 'foo'
|
400
|
+
m2.should == 'faa'
|
401
|
+
end
|
402
|
+
with d do
|
403
|
+
m1.should == 'foooo'
|
404
|
+
m2.should == 'faa'
|
405
|
+
end
|
406
|
+
end
|
176
407
|
|
408
|
+
it 'class overrides at second level' do
|
177
409
|
|
178
410
|
########################################
|
179
|
-
|
411
|
+
# Preamble (from above)
|
180
412
|
########################################
|
413
|
+
c = C.new
|
414
|
+
|
415
|
+
D.inject j { # new version of j pre-defined at injection
|
416
|
+
def m1
|
417
|
+
'foooo'
|
418
|
+
end
|
419
|
+
}
|
420
|
+
|
421
|
+
####################################
|
422
|
+
# Override injections at class level
|
423
|
+
####################################
|
181
424
|
class D < C
|
182
|
-
def m1
|
425
|
+
def m1 # overrides foo from j
|
183
426
|
'fuu'
|
184
427
|
end
|
185
428
|
end
|
186
|
-
C.
|
187
|
-
C.new.
|
188
|
-
D.
|
189
|
-
D.new.
|
429
|
+
C.traits.sym_list.should == [:k, :j]
|
430
|
+
C.new.traits.sym_list.should == [:k, :j]
|
431
|
+
D.traits.sym_list.should == [:j]
|
432
|
+
D.new.traits.sym_list.should == [:j]
|
433
|
+
d = D.new
|
190
434
|
|
191
435
|
# New Objects
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
436
|
+
with D.new do
|
437
|
+
m1.should == 'fuu' # overrided last version from j
|
438
|
+
m2.should == 'faa' # still the same
|
439
|
+
end
|
440
|
+
with C.new do
|
441
|
+
m1.should == 'foo'
|
442
|
+
m2.should == 'faa'
|
443
|
+
end
|
197
444
|
# Existing Objects
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
445
|
+
with c do
|
446
|
+
c.m1.should == 'foo'
|
447
|
+
c.m2.should == 'faa'
|
448
|
+
end
|
449
|
+
with d do
|
450
|
+
d.m1.should == 'fuu' # overrided
|
451
|
+
d.m2.should == 'faa'
|
452
|
+
end
|
453
|
+
|
454
|
+
end
|
202
455
|
|
456
|
+
it 'allows updates to methods at their respective level' do
|
203
457
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
458
|
+
####################################
|
459
|
+
# Preamble ( carry from above)
|
460
|
+
####################################
|
461
|
+
c = C.new
|
462
|
+
|
463
|
+
D.inject j { # new version of j pre-defined at injection
|
464
|
+
def m1
|
465
|
+
'foooo'
|
466
|
+
end
|
467
|
+
}
|
468
|
+
class D < C
|
469
|
+
def m1 # overrides foo from j
|
470
|
+
'fuu'
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
####################################
|
475
|
+
# update K and inherit into D
|
476
|
+
####################################
|
477
|
+
C.send :update, k { # new version of k pre-defined at update
|
478
|
+
def m2 # -- no other version of k in hierarchy
|
209
479
|
'faaxx'
|
210
480
|
end
|
211
481
|
}
|
@@ -213,70 +483,126 @@ describe "the behavior of injectors under class inheritance" do
|
|
213
483
|
# class C
|
214
484
|
# update k # providing k is in scope
|
215
485
|
# end
|
216
|
-
|
217
|
-
C.
|
218
|
-
|
219
|
-
D.
|
220
|
-
|
486
|
+
|
487
|
+
C.traits.sym_list.should == [:k, :j]
|
488
|
+
C.new.traits.sym_list.should == [:k, :j]
|
489
|
+
D.traits.sym_list.should == [:j]
|
490
|
+
D.new.traits.sym_list.should == [:j]
|
491
|
+
d = D.new
|
492
|
+
|
221
493
|
# New Objects
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
494
|
+
with D.new do
|
495
|
+
m2.should == 'faaxx'
|
496
|
+
m1.should == 'fuu'
|
497
|
+
end
|
498
|
+
with C.new do
|
499
|
+
m2.should == 'faaxx' # new version of m1faa
|
500
|
+
m1.should == 'foo' # still the same
|
501
|
+
end
|
227
502
|
# Existing Objects
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
503
|
+
with c do
|
504
|
+
m1.should == 'foo'
|
505
|
+
m2.should == 'faaxx'
|
506
|
+
end
|
507
|
+
with d do
|
508
|
+
m1.should == 'fuu'
|
509
|
+
m2.should == 'faaxx'
|
510
|
+
end
|
511
|
+
|
512
|
+
end
|
232
513
|
|
514
|
+
it 'goes on to other levels' do
|
233
515
|
|
234
|
-
|
516
|
+
####################################
|
517
|
+
# Preamble (carry from above)
|
518
|
+
####################################
|
519
|
+
c = C.new
|
520
|
+
|
521
|
+
D.inject j { # new version of j pre-defined at injection
|
522
|
+
def m1
|
523
|
+
'foooo'
|
524
|
+
end
|
525
|
+
}
|
526
|
+
class D < C
|
527
|
+
def m1 # overrides foo from j
|
528
|
+
'fuu'
|
529
|
+
end
|
530
|
+
end
|
531
|
+
C.send :update, k { # new version of k pre-defined at update
|
532
|
+
def m2 # -- no other version of k in hierarchy
|
533
|
+
'faaxx'
|
534
|
+
end
|
535
|
+
}
|
536
|
+
|
537
|
+
####################################
|
235
538
|
# E inherits from D
|
236
|
-
|
237
|
-
class E < D
|
539
|
+
####################################
|
540
|
+
class E < D # methods are inherited from j at C, D and k update at C
|
238
541
|
end
|
239
|
-
C.
|
240
|
-
C.new.
|
241
|
-
D.
|
242
|
-
D.new.
|
243
|
-
E.
|
244
|
-
E.new.
|
542
|
+
C.traits.sym_list.should == [:k, :j]
|
543
|
+
C.new.traits.sym_list.should == [:k, :j]
|
544
|
+
D.traits.sym_list.should == [:j]
|
545
|
+
D.new.traits.sym_list.should == [:j]
|
546
|
+
E.traits.sym_list.should == []
|
547
|
+
E.new.traits.sym_list.should == []
|
548
|
+
|
549
|
+
d = D.new
|
550
|
+
e = E.new
|
245
551
|
|
246
552
|
# New Objects
|
247
553
|
C.new.m1.should == 'foo'
|
248
554
|
C.new.m2.should == 'faaxx'
|
249
555
|
D.new.m1.should == 'fuu'
|
250
|
-
D.new.m2.should == 'faaxx'
|
556
|
+
D.new.m2.should == 'faaxx' # new objects pass
|
251
557
|
E.new.m1.should == 'fuu'
|
252
558
|
E.new.m2.should == 'faaxx'
|
253
559
|
# Existing Objects
|
254
|
-
e = E.new
|
255
560
|
c.m1.should == 'foo'
|
256
|
-
c.m2.should == 'faaxx'
|
561
|
+
c.m2.should == 'faaxx' # existing objects pass
|
257
562
|
d.m1.should == 'fuu'
|
258
563
|
d.m2.should == 'faaxx'
|
564
|
+
e.m1.should == 'fuu'
|
565
|
+
e.m2.should == 'faaxx'
|
566
|
+
end
|
259
567
|
|
260
|
-
|
568
|
+
this 'new class level override' do
|
569
|
+
|
261
570
|
########################################
|
262
|
-
|
571
|
+
# Preamble (carry from above)
|
263
572
|
########################################
|
264
|
-
|
265
|
-
def m1 # overrides #foo from j at C, D
|
266
|
-
'fuuuu'
|
267
|
-
end
|
268
|
-
end
|
269
|
-
C.injectors.sym_list.should == [:k, :j]
|
270
|
-
C.new.injectors.sym_list.should == [:k, :j]
|
271
|
-
D.injectors.sym_list.should == [:j]
|
272
|
-
D.new.injectors.sym_list.should == [:j]
|
273
|
-
E.injectors.sym_list.should == []
|
274
|
-
E.new.injectors.sym_list.should == []
|
573
|
+
c = C.new
|
275
574
|
|
276
|
-
#
|
277
|
-
|
278
|
-
|
279
|
-
|
575
|
+
D.inject j { # new version of j pre-defined at injection
|
576
|
+
def m1
|
577
|
+
'foooo'
|
578
|
+
end
|
579
|
+
}
|
580
|
+
class D < C
|
581
|
+
def m1 # overrides foo from j
|
582
|
+
'fuu'
|
583
|
+
end
|
584
|
+
end
|
585
|
+
C.send :update, k { # new version of k pre-defined at update
|
586
|
+
def m2 # -- no other version of k in hierarchy
|
587
|
+
'faaxx'
|
588
|
+
end
|
589
|
+
}
|
590
|
+
|
591
|
+
########################################
|
592
|
+
# E overrides D
|
593
|
+
########################################
|
594
|
+
class E < D
|
595
|
+
def m1 # overrides #foo from j at C, D
|
596
|
+
'fuuuu'
|
597
|
+
end
|
598
|
+
end
|
599
|
+
d = D.new
|
600
|
+
e = E.new
|
601
|
+
|
602
|
+
# New Objects
|
603
|
+
C.new.m1.should == 'foo'
|
604
|
+
C.new.m2.should == 'faaxx'
|
605
|
+
D.new.m1.should == 'fuu'
|
280
606
|
D.new.m2.should == 'faaxx'
|
281
607
|
E.new.m1.should == 'fuuuu'
|
282
608
|
E.new.m2.should == 'faaxx'
|
@@ -287,92 +613,133 @@ describe "the behavior of injectors under class inheritance" do
|
|
287
613
|
d.m2.should == 'faaxx'
|
288
614
|
e.m1.should == 'fuuuu'
|
289
615
|
e.m2.should == 'faaxx'
|
290
|
-
|
291
|
-
|
292
|
-
#######################################
|
293
|
-
# ejection
|
294
|
-
#######################################
|
295
|
-
C.eject :j # eject j from C
|
296
|
-
|
297
|
-
C.new.injectors.sym_list.should == [:k]
|
298
|
-
C.injectors.sym_list.should == [:k]
|
299
|
-
D.new.injectors.sym_list.should == [:j]
|
300
|
-
D.injectors.sym_list.should == [:j]
|
301
|
-
E.new.injectors.sym_list.should == []
|
302
|
-
E.injectors.sym_list.should == []
|
303
616
|
|
304
|
-
|
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'
|
311
|
-
# Existing Objects
|
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'
|
617
|
+
end
|
318
618
|
|
619
|
+
describe 'ejection' do
|
319
620
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
C.new.injectors.sym_list.should == []
|
326
|
-
C.injectors.sym_list.should == []
|
327
|
-
D.new.injectors.sym_list.should == [:j]
|
328
|
-
D.injectors.sym_list.should == [:j]
|
329
|
-
E.new.injectors.sym_list.should == []
|
330
|
-
E.injectors.sym_list.should == []
|
621
|
+
before do
|
622
|
+
########################################
|
623
|
+
# Preamble (carry from above)
|
624
|
+
########################################
|
331
625
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
626
|
+
D.inject j { # new version of j pre-defined at injection
|
627
|
+
def m1
|
628
|
+
'foooo'
|
629
|
+
end
|
630
|
+
}
|
631
|
+
class D < C
|
632
|
+
def m1 # overrides foo from j
|
633
|
+
'fuu'
|
634
|
+
end
|
635
|
+
end
|
636
|
+
C.send :update, k { # new version of k pre-defined at update
|
637
|
+
def m2 # -- no other version of k in hierarchy
|
638
|
+
'faaxx'
|
639
|
+
end
|
640
|
+
}
|
641
|
+
|
642
|
+
########################################
|
643
|
+
# E overrides D
|
644
|
+
########################################
|
645
|
+
class E < D
|
646
|
+
def m1 # overrides #foo from j at C, D
|
647
|
+
'fuuuu'
|
648
|
+
end
|
649
|
+
end
|
650
|
+
end
|
651
|
+
|
652
|
+
it 'works with ejection' do
|
653
|
+
|
654
|
+
c = C.new
|
655
|
+
d = D.new
|
656
|
+
e = E.new
|
657
|
+
|
658
|
+
#######################################
|
659
|
+
# ejection
|
660
|
+
#######################################
|
661
|
+
C.eject :j # eject j from C
|
662
|
+
|
663
|
+
C.new.traits.sym_list.should == [:k]
|
664
|
+
C.traits.sym_list.should == [:k]
|
665
|
+
D.new.traits.sym_list.should == [:j]
|
666
|
+
D.traits.sym_list.should == [:j]
|
667
|
+
E.new.traits.sym_list.should == []
|
668
|
+
E.traits.sym_list.should == []
|
669
|
+
|
670
|
+
# New Objects
|
671
|
+
expect{ C.new.m1.should == 'foo'}.to raise_error(NoMethodError) # m1 errors out on C
|
672
|
+
C.new.m2.should == 'faaxx'
|
673
|
+
D.new.m1.should == 'fuu'
|
674
|
+
D.new.m2.should == 'faaxx' # all else is the same...
|
675
|
+
E.new.m1.should == 'fuuuu'
|
676
|
+
E.new.m2.should == 'faaxx'
|
677
|
+
# Existing Objects
|
678
|
+
expect{c.m1.should == 'foo'}.to raise_error(NoMethodError) # m1 errors out on C
|
679
|
+
c.m2.should == 'faaxx'
|
680
|
+
d.m1.should == 'fuu'
|
681
|
+
d.m2.should == 'faaxx'
|
682
|
+
e.m1.should == 'fuuuu'
|
683
|
+
e.m2.should == 'faaxx'
|
684
|
+
|
685
|
+
|
686
|
+
########################################
|
687
|
+
# more ejection
|
688
|
+
########################################
|
689
|
+
C.eject :k # eject the only k
|
690
|
+
|
691
|
+
C.new.traits.sym_list.should == []
|
692
|
+
C.traits.sym_list.should == []
|
693
|
+
D.new.traits.sym_list.should == [:j]
|
694
|
+
D.traits.sym_list.should == [:j]
|
695
|
+
E.new.traits.sym_list.should == []
|
696
|
+
E.traits.sym_list.should == []
|
697
|
+
|
698
|
+
# New Objects
|
699
|
+
expect{ C.new.m1.should == 'foo'}.to raise_error(NoMethodError)
|
700
|
+
expect{ C.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) # # faa errors out
|
701
|
+
D.new.m1.should == 'fuu'
|
702
|
+
expect{ D.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) #faa errors out
|
703
|
+
E.new.m1.should == 'fuuuu'
|
704
|
+
expect{ E.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) #faa was only available thru k at C
|
705
|
+
# Existing Objects
|
706
|
+
expect{c.m1.should == 'foo'}.to raise_error(NoMethodError)
|
707
|
+
expect{c.m2.should == 'faaxx'}.to raise_error(NoMethodError)
|
708
|
+
d.m1.should == 'fuu' # same thing for pre-existing objects
|
709
|
+
expect{d.m2.should == 'faaxx'}.to raise_error(NoMethodError)
|
710
|
+
e.m1.should == 'fuuuu'
|
711
|
+
expect{e.m2.should == 'faaxx'}.to raise_error(NoMethodError)
|
712
|
+
|
713
|
+
|
714
|
+
########################################
|
715
|
+
# more ejection
|
716
|
+
########################################
|
717
|
+
D.eject :j # eject j from D: the only one remaining
|
718
|
+
# -- everything should revert back to class level
|
719
|
+
C.traits.sym_list.should == []
|
720
|
+
C.new.traits.sym_list.should == []
|
721
|
+
D.traits.sym_list.should == []
|
722
|
+
D.new.traits.sym_list.should == []
|
723
|
+
E.traits.sym_list.should == []
|
724
|
+
E.new.traits.sym_list.should == []
|
725
|
+
|
726
|
+
# New Objects
|
727
|
+
expect{ C.new.m1.should == 'foo'}.to raise_error(NoMethodError) # no actual #foo on class
|
728
|
+
expect{ C.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) # ''
|
729
|
+
D.new.m1.should == 'fuu' # retains overrides from D
|
730
|
+
expect{ D.new.m2.should == 'faaxx'}.to raise_error(NoMethodError)
|
731
|
+
E.new.m1.should == 'fuuuu' # retains overrides from E
|
732
|
+
expect{ E.new.m2.should == 'faaxx'}.to raise_error(NoMethodError)
|
733
|
+
# Existing Objects
|
734
|
+
expect{c.m1.should == 'foo'}.to raise_error(NoMethodError)
|
735
|
+
expect{c.m2.should == 'faaxx'}.to raise_error(NoMethodError)
|
736
|
+
d.m1.should == 'fuu' # same for pre-existing objects
|
737
|
+
expect{d.m2.should == 'faaxx'}.to raise_error(NoMethodError)
|
738
|
+
e.m1.should == 'fuuuu'
|
739
|
+
expect{e.m2.should == 'faaxx'}.to raise_error(NoMethodError)
|
740
|
+
|
741
|
+
end
|
742
|
+
end
|
376
743
|
|
377
744
|
describe 'some special cases' do
|
378
745
|
|
@@ -383,12 +750,11 @@ describe "the behavior of injectors under class inheritance" do
|
|
383
750
|
|
384
751
|
# Define a blanck Injector
|
385
752
|
|
386
|
-
|
753
|
+
trait :j1
|
387
754
|
|
755
|
+
# Apply to hierarchy while defining
|
388
756
|
|
389
|
-
#
|
390
|
-
|
391
|
-
C1.inject j1 do # apply definitions
|
757
|
+
C1.inject j1 do # same as pre-defined
|
392
758
|
def m1
|
393
759
|
'm1'
|
394
760
|
end
|
@@ -411,11 +777,11 @@ describe "the behavior of injectors under class inheritance" do
|
|
411
777
|
|
412
778
|
|
413
779
|
############################
|
414
|
-
#
|
780
|
+
# NEW VERSION!
|
415
781
|
############################
|
416
|
-
j1 do
|
417
|
-
def m1 # -- was applied to C1
|
418
|
-
'm1xx' #
|
782
|
+
j1 do
|
783
|
+
def m1 # -- previous was applied to C1
|
784
|
+
'm1xx' # this #m1 only defined in the Virtual Method Cache
|
419
785
|
end
|
420
786
|
end
|
421
787
|
|
@@ -426,7 +792,7 @@ describe "the behavior of injectors under class inheritance" do
|
|
426
792
|
E1.new.m1.should == 'm1'
|
427
793
|
|
428
794
|
|
429
|
-
E1.inject j1 #
|
795
|
+
E1.inject j1 # APPLY to hierarchy on E!
|
430
796
|
|
431
797
|
C1.new.m1.should == 'm1' # same
|
432
798
|
D1.new.m1.should == 'm1' # same
|
@@ -441,34 +807,30 @@ describe "the behavior of injectors under class inheritance" do
|
|
441
807
|
|
442
808
|
# Define a blank Injector
|
443
809
|
|
444
|
-
|
445
|
-
|
810
|
+
trait :j2
|
446
811
|
|
447
|
-
# Apply
|
812
|
+
# Apply full definition to an ancestor
|
448
813
|
|
449
814
|
Object.inject j2 do
|
450
815
|
def m1
|
451
816
|
'm1xx'
|
452
817
|
end
|
453
818
|
end
|
454
|
-
|
455
|
-
|
456
|
-
# Call on the Injector
|
457
|
-
|
819
|
+
# same effect as above
|
458
820
|
C2.new.m1.should == 'm1xx' # call Injector
|
459
821
|
|
460
822
|
|
461
823
|
############################
|
462
|
-
#
|
824
|
+
# NEW VERSION!
|
463
825
|
############################
|
464
826
|
|
465
|
-
j2 do # NEW VERSION!
|
466
|
-
def m1 # -- was applied to Object in the hierarchy
|
467
|
-
'm1' #
|
827
|
+
j2 do # NEW VERSION!
|
828
|
+
def m1 # -- previous was applied to Object in the hierarchy
|
829
|
+
'm1' # this #m1 only defined in the Virtual Method Cache
|
468
830
|
end
|
469
831
|
end
|
470
832
|
|
471
|
-
# Calls un-afffected
|
833
|
+
# Calls un-afffected !!
|
472
834
|
|
473
835
|
C2.new.m1.should == 'm1xx' # still using the previous version --no changes
|
474
836
|
|
@@ -488,12 +850,11 @@ describe "the behavior of injectors under class inheritance" do
|
|
488
850
|
|
489
851
|
|
490
852
|
###########################
|
491
|
-
#
|
853
|
+
# Apply new version on C
|
492
854
|
###########################
|
493
855
|
|
494
856
|
C2.inject j2
|
495
857
|
|
496
|
-
|
497
858
|
# Calls changed from C on up
|
498
859
|
|
499
860
|
C2.new.m1.should == 'm1'
|
@@ -519,40 +880,41 @@ describe "the behavior of injectors under class inheritance" do
|
|
519
880
|
|
520
881
|
# Define a Blank Injector
|
521
882
|
|
522
|
-
|
883
|
+
trait :j3
|
523
884
|
|
524
885
|
|
525
|
-
# Apply the blank
|
886
|
+
# Apply the blank trait
|
526
887
|
|
527
888
|
C3.inject j3
|
528
889
|
|
890
|
+
############################
|
891
|
+
# NEW VERSION!
|
892
|
+
############################
|
529
893
|
|
530
|
-
#
|
531
|
-
|
532
|
-
j3 do # NEW VERSION!
|
894
|
+
j3 do #
|
533
895
|
def m1 # -- never applied to Object in the hierarchy
|
534
|
-
'm1' #
|
896
|
+
'm1' # this #m1 only defined in the Virtual Method Cache
|
535
897
|
end
|
536
898
|
end
|
537
899
|
|
538
900
|
|
539
901
|
# C3 calls
|
540
902
|
|
541
|
-
C3.new.m1.should == 'm1' # call works
|
903
|
+
C3.new.m1.should == 'm1' # call works from VMC
|
542
904
|
|
543
905
|
|
544
906
|
# D3 inherits from C3
|
545
907
|
|
546
908
|
class D3 < C3
|
547
909
|
end
|
548
|
-
D3.new.m1.should == 'm1' # inherited call
|
910
|
+
D3.new.m1.should == 'm1' # inherited call from VMC
|
549
911
|
|
550
912
|
|
551
913
|
# E3 inherits from D3
|
552
914
|
|
553
915
|
class E3 < D3
|
554
916
|
end
|
555
|
-
E3.new.m1.should == 'm1' # inherited call
|
917
|
+
E3.new.m1.should == 'm1' # inherited call from VMC
|
556
918
|
|
557
919
|
|
558
920
|
###################################
|
@@ -562,19 +924,20 @@ describe "the behavior of injectors under class inheritance" do
|
|
562
924
|
|
563
925
|
j3 do # NEW VERSION!
|
564
926
|
def m1 # -- never applied to Object in the hierarchy
|
565
|
-
'm1xx' #
|
927
|
+
'm1xx' # this #m1 only defined in the Virtual Method Cache
|
566
928
|
end
|
567
929
|
end
|
568
930
|
|
569
|
-
|
931
|
+
##############################
|
570
932
|
# Calls are also re-defined
|
571
|
-
|
933
|
+
##############################
|
934
|
+
|
572
935
|
C3.new.m1.should == 'm1xx' # call is redefined
|
573
936
|
D3.new.m1.should == 'm1xx' # ''
|
574
937
|
E3.new.m1.should == 'm1xx' # ''
|
575
938
|
|
576
939
|
|
577
|
-
# Apply the
|
940
|
+
# Apply the full Injector onto E3
|
578
941
|
|
579
942
|
E3.inject j3 # Attaches this version onto E only!!
|
580
943
|
|
@@ -586,13 +949,13 @@ describe "the behavior of injectors under class inheritance" do
|
|
586
949
|
E3.new.m1.should == 'm1xx' # => from applied version
|
587
950
|
|
588
951
|
|
589
|
-
|
590
|
-
#
|
591
|
-
|
952
|
+
############################
|
953
|
+
# NEW VERSION!
|
954
|
+
############################
|
592
955
|
|
593
|
-
j3 do
|
956
|
+
j3 do
|
594
957
|
def m1 # -- never applied to Object in the hierarchy
|
595
|
-
'-----' #
|
958
|
+
'-----' # this #m1 only defined in the Virtual Method Cache
|
596
959
|
end
|
597
960
|
end
|
598
961
|
|
@@ -603,767 +966,10 @@ describe "the behavior of injectors under class inheritance" do
|
|
603
966
|
D3.new.m1.should == '-----' # ''
|
604
967
|
|
605
968
|
E3.new.m1.should == 'm1xx' # NOT REDEFINED!!
|
606
|
-
# from applied version
|
607
|
-
|
608
|
-
end
|
609
|
-
|
610
|
-
end
|
611
|
-
end
|
612
|
-
|
613
|
-
describe "regular Injector internal inheritance" do
|
614
|
-
|
615
|
-
it 'carries current methods onto Injector Versions/Tags' do
|
616
|
-
|
617
|
-
# Define injector
|
618
|
-
|
619
|
-
jack :bounce
|
620
|
-
|
621
|
-
bounce do
|
622
|
-
def sound
|
623
|
-
'splat splat'
|
624
|
-
end
|
625
|
-
end
|
626
|
-
|
627
|
-
|
628
|
-
# Define Tag with new methods
|
629
|
-
|
630
|
-
TagOne = bounce do
|
631
|
-
def bounce
|
632
|
-
'boing boing'
|
633
|
-
end
|
634
|
-
end
|
635
|
-
|
636
|
-
|
637
|
-
# Apply Tag
|
638
|
-
|
639
|
-
class Ball
|
640
|
-
inject TagOne
|
641
|
-
end
|
642
|
-
Ball.new.bounce.should == 'boing boing'
|
643
|
-
|
644
|
-
|
645
|
-
class Spring
|
646
|
-
inject TagOne
|
647
|
-
end
|
648
|
-
Spring.new.bounce.should == 'boing boing'
|
649
|
-
|
650
|
-
|
651
|
-
# Inherited methods from :bounce
|
652
|
-
|
653
|
-
Ball.new.sound.should == 'splat splat'
|
654
|
-
Spring.new.sound.should == 'splat splat'
|
655
|
-
|
656
|
-
end
|
657
|
-
|
658
|
-
a "more complex example: effectively working Ruby's multiple inheritance" do
|
969
|
+
# from full applied version
|
659
970
|
|
660
|
-
jack :player do
|
661
|
-
def sound
|
662
|
-
'Lets make some music'
|
663
|
-
end
|
664
|
-
end
|
665
|
-
|
666
|
-
TapePlayer = player do
|
667
|
-
def play
|
668
|
-
return 'Tape playing...' + sound()
|
669
|
-
end
|
670
|
-
end
|
671
|
-
|
672
|
-
CDPlayer = player do
|
673
|
-
def play
|
674
|
-
return 'CD playing...' + sound()
|
675
|
-
end
|
676
|
-
end
|
677
|
-
|
678
|
-
class BoomBox
|
679
|
-
include TapePlayer
|
680
|
-
|
681
|
-
def on
|
682
|
-
play
|
683
|
-
end
|
684
|
-
end
|
685
|
-
|
686
|
-
class JukeBox < BoomBox
|
687
|
-
inject CDPlayer
|
688
971
|
end
|
689
972
|
|
690
|
-
BoomBox.new.on.should == 'Tape playing...Lets make some music'
|
691
|
-
JukeBox.new.on.should == 'CD playing...Lets make some music'
|
692
|
-
|
693
|
-
#...
|
694
|
-
|
695
|
-
jack :speakers
|
696
|
-
|
697
|
-
Bass = speakers do
|
698
|
-
def sound
|
699
|
-
super + '...boom boom boom...'
|
700
|
-
end
|
701
|
-
end
|
702
|
-
|
703
|
-
JukeBox.inject Bass
|
704
|
-
JukeBox.new.on.should == 'CD playing...Lets make some music...boom boom boom...'
|
705
|
-
|
706
|
-
end
|
707
|
-
|
708
|
-
|
709
|
-
it 'works accross compound injectors' do
|
710
|
-
|
711
|
-
jack :S1
|
712
|
-
|
713
|
-
S1 do
|
714
|
-
include jack :s2 do
|
715
|
-
def s2m1
|
716
|
-
:s2m1
|
717
|
-
end
|
718
|
-
include jack :s3 do
|
719
|
-
def s3m1
|
720
|
-
:s3m1
|
721
|
-
end
|
722
|
-
include jack :s4 do
|
723
|
-
def s4m1
|
724
|
-
:s4m1
|
725
|
-
end
|
726
|
-
end
|
727
|
-
end
|
728
|
-
end
|
729
|
-
end
|
730
|
-
|
731
|
-
S1().s2.s3.s4 # injector pipeline!
|
732
|
-
|
733
|
-
|
734
|
-
# Apply the injectors
|
735
|
-
|
736
|
-
class CompoundContainer
|
737
|
-
include S1()
|
738
|
-
end
|
739
|
-
|
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
|
799
|
-
|
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
|
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
|
864
|
-
|
865
|
-
end
|
866
|
-
|
867
|
-
describe 'jit inheriatnce' do
|
868
|
-
|
869
|
-
before do
|
870
|
-
injector :Tagger
|
871
|
-
|
872
|
-
end
|
873
|
-
|
874
|
-
after do
|
875
|
-
Tagger(:implode)
|
876
|
-
|
877
|
-
end
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
it "follows a just-in-time inheritance policy" do
|
882
|
-
|
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
|
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
|
-
|
1087
|
-
end
|
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
|
1099
|
-
|
1100
|
-
module Mod1
|
1101
|
-
def m1
|
1102
|
-
'one'
|
1103
|
-
end
|
1104
|
-
end
|
1105
|
-
|
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
|
1117
|
-
|
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])
|
1121
|
-
|
1122
|
-
# test it
|
1123
|
-
|
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
|
-
|
1136
|
-
end
|
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
|
1147
|
-
end
|
1148
|
-
|
1149
|
-
module Mod2
|
1150
|
-
def m1
|
1151
|
-
3
|
1152
|
-
end
|
1153
|
-
end
|
1154
|
-
|
1155
|
-
Object.new.extend(Tagger(Mod2)).m1.should == 6
|
1156
|
-
Object.new.extend(Tagger(Mod2)).m2.should == :m2
|
1157
|
-
|
1158
|
-
end
|
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
|
1183
|
-
|
1184
|
-
|
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
|
-
|
1202
|
-
end
|
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'
|
1215
|
-
end
|
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
|
-
|
1234
|
-
end
|
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
|
-
|
1270
|
-
end
|
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
|
-
|
1312
|
-
end
|
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
|
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
|
-
|
1361
|
-
end
|
1362
|
-
|
1363
973
|
end
|
1364
974
|
end
|
1365
975
|
|
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+'))
|