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.
@@ -1,34 +1,34 @@
1
1
  require "spec_helper"
2
2
  =begin rdoc
3
3
 
4
- Name spacing of injectors
4
+ Name spacing of traits
5
5
  Author: LHA
6
6
 
7
7
 
8
8
 
9
- Description of the difference between the different namespacing options of injectors:
9
+ Description of the difference between the different namespacing options of traits:
10
10
 
11
- injector :Main
11
+ trait :Main
12
12
  vs.
13
- injector :main
13
+ trait :main
14
14
 
15
15
  module X
16
- injector :Some_Injector
16
+ trait :Some_Injector
17
17
  vs.
18
- injector :some_injector
18
+ trait :some_trait
19
19
  end
20
20
 
21
21
  class Y
22
- injector :Other_Injector
22
+ trait :Other_Injector
23
23
  vs.
24
- injector :other_injector
24
+ trait :other_trait
25
25
  end
26
26
 
27
27
  =end
28
28
 
29
29
  ###########################
30
- injector :Major
31
- injector :minor
30
+ trait :Major
31
+ trait :minor
32
32
  ###########################
33
33
 
34
34
  # upper case vs lower case: semantically equivalent
@@ -73,8 +73,8 @@ end
73
73
 
74
74
  ###############################
75
75
  module X
76
- injector :Maxi # use sparringly
77
- injector :mini
76
+ trait :Maxi # use sparringly
77
+ trait :mini
78
78
  end
79
79
  ################################
80
80
 
@@ -144,9 +144,9 @@ end
144
144
  # Should follow the same line
145
145
  #
146
146
  class Y
147
- injector :Other_Injector
147
+ trait :Other_Injector
148
148
  # vs.
149
- injector :other_injector
149
+ trait :other_trait
150
150
  end
151
151
  #
152
152
  # No example needed!!
@@ -156,12 +156,12 @@ end
156
156
 
157
157
 
158
158
  # Tied to the idea of Injector Name Spaces is the one of Injector Version Naming/Tagging. In order to make is easier to
159
- # work with injector versions there is a need to tag/name the different versions for later use.
160
- describe 'injector Tagging/Naming and its relationship to Injector Versioning' do
159
+ # work with trait versions there is a need to tag/name the different versions for later use.
160
+ describe 'trait Tagging/Naming and its relationship to Injector Versioning' do
161
161
 
162
162
  there 'is way to tag/name a particular version for later reuse' do
163
163
 
164
- injector :Bar
164
+ trait :Bar
165
165
 
166
166
  Tag = Bar do
167
167
  def foo_bar
@@ -839,6 +839,32 @@ describe Injectors, :injectors do
839
839
 
840
840
  end
841
841
 
842
+ it 'ejects inherited tags' do
843
+
844
+ EjectionTag1 = jack :ejection_test do
845
+ def m1
846
+ 2
847
+ end
848
+ end
849
+
850
+ EjectionTag2 = ejection_test do
851
+ def m1
852
+ super + 2 # override --jit inheritance
853
+ end
854
+ end
855
+
856
+ o = Object.new.enrich EjectionTag2
857
+ o.m1.should == 4
858
+ # o.metaclass.ancestors.to_s.should match(/EjectionTag2.*EjectionTag1/)
859
+
860
+ o.eject EjectionTag2
861
+ expect{o.m1}.to raise_error(NoMethodError)
862
+ o.metaclass.ancestors.to_s.should_not match(/EjectionTag2/)
863
+ o.metaclass.ancestors.to_s.should_not match(/EjectionTag2.*EjectionTag1/)
864
+ o.metaclass.ancestors.to_s.should_not match(/EjectionTag1/)
865
+
866
+ end
867
+
842
868
  end
843
869
  end
844
870
 
@@ -2,29 +2,29 @@ require "spec_helper"
2
2
 
3
3
  include Injectors
4
4
 
5
- describe 'Injector versioning:', :injectors do
6
- # subsequent redefinitions of methods constitute another version of the injector. Injector
5
+ describe 'Injector versioning:', :traits do
6
+ # subsequent redefinitions of methods constitute another version of the trait. Injector
7
7
  # versioning is the term used to identify a feature in the code that produces an artifact of injection which contains a
8
- # certain set of methods and their associated outputs and represents a snapshot of that injector up until the point it
9
- # gets applied to an object. From, that point on the object contains only that version of methods from that injector, and
10
- # any subsequent overrides to those methods are only members of the "prolongation" of the injector and do not become part
8
+ # certain set of methods and their associated outputs and represents a snapshot of that trait up until the point it
9
+ # gets applied to an object. From, that point on the object contains only that version of methods from that trait, and
10
+ # any subsequent overrides to those methods are only members of the "prolongation" of the trait and do not become part
11
11
  # of the object of injection unless some form of reinjection occurs. Newer versions of methods only become part of newer
12
12
  # objects or newer injections into existing targets'
13
13
 
14
- describe 'injector versioning and its relationship to object instances' do
14
+ describe 'trait versioning and its relationship to object instances' do
15
15
 
16
- the 'injector versioning uses a snapshot of the injector`s existing methods up to the point of injection' do
17
- # using only that version of methods as the object of injection. AA4ny overrides to methods in any subsequent injector prolongations
18
- # do not take effect in this target. AA4ny new methods added to the injector do become available to the target, although
16
+ the 'trait versioning uses a snapshot of the trait`s existing methods up to the point of injection' do
17
+ # using only that version of methods as the object of injection. AA4ny overrides to methods in any subsequent trait prolongations
18
+ # do not take effect in this target. AA4ny new methods added to the trait do become available to the target, although
19
19
  # may contain internal references to newer versions of the target methods. This ensures to keep everyting working correctly.'
20
20
 
21
21
  #___________________
22
- # injector declaration
23
- injector :My_injector
22
+ # trait declaration
23
+ trait :My_trait
24
24
 
25
25
  #___________________
26
- # injector first prolongation
27
- My_injector do
26
+ # trait first prolongation
27
+ My_trait do
28
28
  def bar
29
29
  :a_bar # version bar.1
30
30
  end
@@ -34,12 +34,12 @@ describe 'Injector versioning:', :injectors do
34
34
  end
35
35
 
36
36
  object1 = Object.new
37
- object1.enrich My_injector() # apply the injector --first snapshot
37
+ object1.enrich My_trait() # apply the trait --first snapshot
38
38
  object1.bar.should == :a_bar # pass the test
39
39
 
40
40
  #__________________
41
- # injector second prolongation
42
- My_injector do
41
+ # trait second prolongation
42
+ My_trait do
43
43
  def bar
44
44
  :some_larger_bar # version bar.2 ... re-defines bar
45
45
  end
@@ -49,7 +49,7 @@ describe 'Injector versioning:', :injectors do
49
49
  end
50
50
 
51
51
  object2 = Object.new
52
- object2.enrich My_injector() # apply the injector --second snapshot
52
+ object2.enrich My_trait() # apply the trait --second snapshot
53
53
  object2.bar.should == :some_larger_bar
54
54
 
55
55
  # result
@@ -66,7 +66,7 @@ describe 'Injector versioning:', :injectors do
66
66
 
67
67
  #_________________
68
68
  # re-injection
69
- enrich My_injector() # re-injection on any object instance
69
+ enrich My_trait() # re-injection on any object instance
70
70
  bar.should == :some_larger_bar # bar.2 now available
71
71
 
72
72
  expect{some_other_function}.to_not raise_error # some_other_function.1 is present
@@ -77,7 +77,7 @@ describe 'Injector versioning:', :injectors do
77
77
 
78
78
  o = Object.new
79
79
 
80
- injector :some_methods do
80
+ trait :some_methods do
81
81
  def meth arg
82
82
  arg
83
83
  end
@@ -103,19 +103,19 @@ describe 'Injector versioning:', :injectors do
103
103
 
104
104
  end
105
105
 
106
- describe "injector versioning and its relationship to classes" do
107
- # similar to object level versioning in that it uses a snapshot of the injector`s existing methods up to the point of injection, using only
106
+ describe "trait versioning and its relationship to classes" do
107
+ # similar to object level versioning in that it uses a snapshot of the trait`s existing methods up to the point of injection, using only
108
108
  # that version of methods as the object of injection. But, unlike object level versioning, because class injection is static, reinjection
109
109
  # does not change the class unless we use the Strategy Pattern which completely changes the class's strategy of methods"
110
110
 
111
- the "class injector versioning is similar to object injector versioning" do
111
+ the "class trait versioning is similar to object trait versioning" do
112
112
 
113
113
  #___________________
114
- # injector declaration:
115
- injector :Versions
114
+ # trait declaration:
115
+ trait :Versions
116
116
 
117
117
  #___________________
118
- # injector first prolongation
118
+ # trait first prolongation
119
119
  Version1 = Versions do
120
120
  def meth arg # version meth.1
121
121
  arg ** arg
@@ -127,7 +127,7 @@ describe 'Injector versioning:', :injectors do
127
127
  end
128
128
 
129
129
  #_________________
130
- # injector second prolongation
130
+ # trait second prolongation
131
131
  Version2 = Versions do
132
132
  def meth arg1, arg2 # version meth.2 ... redefines meth.1
133
133
  arg1 * arg2
@@ -142,7 +142,7 @@ describe 'Injector versioning:', :injectors do
142
142
  # result
143
143
  #############################
144
144
  Two.new.meth(2,4).should == 8 # meth.2
145
- # two different injector versions
145
+ # two different trait versions
146
146
  One.new.meth(3).should == 27 # meth.1
147
147
  #############################
148
148
  #
@@ -162,7 +162,7 @@ describe 'Injector versioning:', :injectors do
162
162
 
163
163
  end
164
164
 
165
- the 'way to class level injector updates is through the Strategy Pattern' do
165
+ the 'way to class level trait updates is through the Strategy Pattern' do
166
166
 
167
167
  # DO NOT want to necessarily update older clients of the class
168
168
  # but possible if needed
@@ -170,7 +170,7 @@ describe 'Injector versioning:', :injectors do
170
170
  class One
171
171
  eject Version1 # eject version 1
172
172
 
173
- inject Version2 # re-inject with prolonged injector -- can be any version
173
+ inject Version2 # re-inject with prolonged trait -- can be any version
174
174
  end
175
175
  One.new.meth(4,5).should == 20 # meth.2 now available!!
176
176
 
@@ -205,7 +205,7 @@ describe 'Injector versioning:', :injectors do
205
205
 
206
206
  class Freak
207
207
 
208
- injector :freaky
208
+ trait :freaky
209
209
  freaky do
210
210
  def twitch
211
211
  '_-=-_-=-_-=-_-=-_'
@@ -255,11 +255,11 @@ describe 'Injector versioning:', :injectors do
255
255
  end
256
256
  end
257
257
 
258
- describe "utility of injector versioning: " do
258
+ describe "utility of trait versioning: " do
259
259
 
260
260
  it 'allows to easily override methods without affecting other parts of your program' do
261
261
 
262
- J1 = injector :j do
262
+ J1 = trait :j do
263
263
  def meth(arg)
264
264
  arg
265
265
  end
@@ -285,11 +285,11 @@ describe 'Injector versioning:', :injectors do
285
285
 
286
286
  end
287
287
 
288
- the "local binding of injectors" do
288
+ the "local binding of traits" do
289
289
 
290
290
  #_____________________
291
- # injector declaration
292
- VersionOne = injector :functionality do
291
+ # trait declaration
292
+ VersionOne = trait :functionality do
293
293
  def basic arg # version basic.1
294
294
  arg * 2
295
295
  end
@@ -300,7 +300,7 @@ describe 'Injector versioning:', :injectors do
300
300
 
301
301
 
302
302
  #_____________________
303
- # injector prolongation
303
+ # trait prolongation
304
304
  VersionTwo = functionality do
305
305
  def basic arg # basic.2 ... basic.1 redefined
306
306
  arg * 3
@@ -321,7 +321,7 @@ describe 'Injector versioning:', :injectors do
321
321
 
322
322
  o.basic(1).should == 2 # basic.1
323
323
  # debugger
324
- o.compound.should == 11 # compound.1 --local injector binding
324
+ o.compound.should == 11 # compound.1 --local trait binding
325
325
 
326
326
  ###################################
327
327
  # This ensures #compound.1 keeps bound
@@ -0,0 +1,663 @@
1
+ require "spec_helper"
2
+
3
+ describe 'jit inheriatnce' do
4
+
5
+ before do
6
+
7
+ suppress_warnings do
8
+
9
+ #
10
+ # Trait
11
+ #
12
+ trait :Functionality
13
+
14
+ #
15
+ # Works like class inheritance
16
+ #
17
+ Tag1 = Functionality do
18
+ def m1
19
+ 1
20
+ end
21
+
22
+ def m2
23
+ :m2
24
+ end
25
+ end
26
+
27
+ Functionality do
28
+ def other # No overrides No inheritance
29
+ 'other' # -- same ancestors as before
30
+ end # -- normal trait inheritance
31
+ end
32
+
33
+ Tag2 = Functionality do
34
+ def m1 # The :m1 override invokes JIT inheritance
35
+ super + 1 # -- Tag1 is added as ancestor
36
+ end # -- allows the use of super
37
+
38
+ def m3
39
+ 'em3'
40
+ end
41
+ end
42
+
43
+ class AA6
44
+ inject Tag2
45
+ end
46
+
47
+ Tag3 = Functionality() do
48
+ def m1
49
+ super * 2 # second override to #m1
50
+ end # -- Tag2 added as ancestor
51
+ def m3
52
+ super * 2 # first override to #m3
53
+ end
54
+ end
55
+
56
+ class AA7
57
+ inject Tag3
58
+ end
59
+
60
+ end
61
+ end
62
+
63
+ after do
64
+
65
+ suppress_warnings do
66
+
67
+ Tag1 = nil
68
+ Tag2 = nil
69
+ Tag3 = nil
70
+
71
+ end
72
+
73
+ Functionality(:implode)
74
+
75
+ end
76
+
77
+ it 'works under boejct extension' do
78
+
79
+ o = Object.new.extend Tag3
80
+ o.m1.should == 4
81
+
82
+ end
83
+
84
+ it 'also works under class inclusion' do
85
+
86
+ #
87
+ # Under Inclusion
88
+ #
89
+ class AA6
90
+ inject Tag2
91
+ end
92
+ aa6 = AA6.new
93
+
94
+ # JIT inherited
95
+ aa6.m1.should == 2
96
+ aa6.m3.should == 'em3'
97
+
98
+ # Version inherited
99
+ aa6.m2.should == :m2
100
+ aa6.other.should == 'other'
101
+
102
+ Functionality().tags.should == [Tag1, Tag2, Tag3]
103
+
104
+ end
105
+
106
+ it 'goes on down the levels' do
107
+
108
+ #
109
+ # Different client/Diferent Tag
110
+ #
111
+ class AA7
112
+ inject Tag3
113
+ end
114
+ aa7 = AA7.new
115
+
116
+ # JIT inherited
117
+ aa7.m1.should == 4
118
+ aa7.m3.should == 'em3em3'
119
+
120
+ # regular inheritance
121
+ aa7.m2.should == :m2
122
+ aa7.other.should == 'other'
123
+
124
+ Functionality().tags.should == [Tag1, Tag2, Tag3]
125
+
126
+ end
127
+
128
+ it 'keeps the main trait in sync with the last tag' do
129
+
130
+ o = Object.new.extend Tag3
131
+ p = Object.new.extend Functionality()
132
+
133
+ # test it
134
+
135
+ o.m1.should == 4
136
+ p.m1.should == 4
137
+
138
+ end
139
+
140
+ it 'allows rebasing individual methods' do
141
+
142
+ #
143
+ # Another prolongation: back to basics
144
+ #
145
+ Tag4 = Functionality() do
146
+ def m1 # another override but no call to #super
147
+ :m1 # -- just simple override
148
+ end # -- could be tagged if needed
149
+ end
150
+
151
+ # test it
152
+
153
+ o = Object.new.extend( Tag4 )
154
+
155
+ # new version of #m1 !!
156
+ o.m1.should == :m1
157
+
158
+ # JIT inherited
159
+ o.m3.should == 'em3em3' # old jiti version of m3
160
+
161
+ # Version inherited
162
+ o.m2.should == :m2 # old version of m2
163
+ o.other.should == 'other'
164
+
165
+ # Total Tags
166
+
167
+ Functionality().tags.should == [Tag1, Tag2, Tag3, Tag4]
168
+
169
+ end
170
+
171
+ it 'still holds on to earlier tag definitions' do
172
+
173
+ #
174
+ # Test previous Tags are unaffected !!
175
+ #
176
+ AA6.new.m1.should == 2 # includes Tag2
177
+ AA6.new.m2.should == :m2
178
+ AA6.new.m3.should == 'em3'
179
+
180
+ AA7.new.m1.should == 4 # includes Tag3
181
+ AA7.new.m2.should == :m2
182
+ AA7.new.m3.should == 'em3em3'
183
+
184
+ #
185
+ # other clients
186
+ #
187
+ class AA6B
188
+ inject Tag2
189
+ end
190
+ aa6b = AA6B.new
191
+
192
+ aa6b.m1.should == 2
193
+ aa6b.m2.should == :m2
194
+ aa6b.m3.should == 'em3'
195
+
196
+ end
197
+
198
+ it 'keeps the VMC in proper working order' do
199
+
200
+ #
201
+ # VMC (Virtual Method Cache) method
202
+ #
203
+ Functionality() do
204
+ def m4
205
+ :m4
206
+ end
207
+ end
208
+
209
+ class AA6B
210
+ inject Tag2
211
+ end
212
+ aa6b = AA6B.new
213
+
214
+ # jit inherited
215
+ aa6b.m1.should == 2
216
+ aa6b.m3.should == 'em3'
217
+
218
+ # version inherited
219
+ aa6b.m2.should == :m2
220
+ aa6b.other.should == 'other'
221
+
222
+ aa6b.m4.should == :m4 # vmc method
223
+
224
+ # other clients of the VMC
225
+ AA6.new.m4.should == :m4
226
+ AA7.new.m4.should == :m4
227
+
228
+ end
229
+
230
+ it "allows further ancestor injection" do
231
+
232
+ module Mod1
233
+ def m4
234
+ :m4
235
+ end
236
+ end
237
+
238
+ Tag5 = Functionality(Mod1) do
239
+
240
+ include Mod1 # alternatively
241
+
242
+ def m1
243
+ super * 2
244
+ end
245
+ def m3
246
+ :m3 # m3 is rebased
247
+ end
248
+ end
249
+
250
+ # test it
251
+
252
+ # jit inherited
253
+ Object.new.extend(Tag5).m1.should == 8 # from Tag3
254
+
255
+ # version inherited
256
+ Object.new.extend(Tag5).m2.should == :m2 # from Tag1
257
+
258
+ # rebased
259
+ Object.new.extend(Tag5).m3.should == :m3 # from Tag5
260
+
261
+ # ancestor injection
262
+ Object.new.extend(Tag5).m4.should == :m4 # from Mod1
263
+
264
+ end
265
+
266
+ it "also allows on the fly overrides" do
267
+
268
+ #
269
+ # On the fly overrides
270
+ #
271
+ obj = Object.new.extend(
272
+ Functionality {
273
+ def m1
274
+ super + 3 # on top of Tag1, Tag2, Tag3
275
+ end
276
+ def m4
277
+ :m4
278
+ end
279
+ })
280
+
281
+ # new jiti override
282
+ obj.m1.should == 7
283
+
284
+ # version inherited
285
+ obj.m2.should == :m2
286
+ obj.m3.should == 'em3em3'
287
+ obj.m4.should == :m4
288
+
289
+ # other prolongation
290
+
291
+ Object.new.extend(Functionality(){
292
+ def m3
293
+ super * 2
294
+ end
295
+ }).m3.should == 'em3em3em3em3'
296
+
297
+ end
298
+
299
+ it "blocks external ancestor intrusion enforcing internal trait consistency" do
300
+
301
+ #########################################
302
+ # Masks Ancestor intrussion
303
+ #
304
+
305
+ Tag6 = Functionality do
306
+ def m1 # Injector has internal base
307
+ 1
308
+ end
309
+ end
310
+
311
+ module Mod1
312
+ def m1
313
+ 'one'
314
+ end
315
+ end
316
+
317
+ Tag7 = Functionality(Mod1) do # Mod1 attempts to intrude on base
318
+
319
+ include Mod1
320
+
321
+ def m1
322
+ super * 2
323
+ end
324
+ end
325
+
326
+ # test it
327
+
328
+ o = Object.new.extend(Tag7)
329
+ # jit inherited
330
+ o.m1.should == 2 # no such luck!!
331
+
332
+ p = Object.new.extend(Functionality())
333
+ # jit inherited
334
+ p.m1.should == 2 # no such luck!!
335
+
336
+ # version inherited
337
+ o.m2.should == :m2 # from Tag1
338
+ p.m2.should == :m2
339
+
340
+ end
341
+
342
+ it 'allows overriding methods further down the tree' do
343
+
344
+ Tag8 = Functionality do
345
+ def m1
346
+ 1
347
+ end
348
+ def m2 # original definition
349
+ 2
350
+ end
351
+ end
352
+ Tag9 = Functionality do
353
+ def m1
354
+ 'm1'
355
+ end # skipped #m2
356
+ end
357
+ Tag10 = Functionality do
358
+ def m1
359
+ super * 2
360
+ end
361
+ def m2
362
+ super * 2 # override # m2 two levels down
363
+ end
364
+ end
365
+ class AA10
366
+ inject Tag10
367
+ end
368
+
369
+ # test it
370
+
371
+ AA10.new.m1.should == 'm1m1'
372
+ AA10.new.m2 == 4
373
+
374
+ end
375
+
376
+ it 'allows rebasing (start fresh) methods at any level' do
377
+
378
+ Tag11 = Functionality do
379
+ def m1
380
+ 1 # rebase Tag3
381
+ end
382
+ end
383
+
384
+ class AA11
385
+ inject Functionality() do
386
+ def m1
387
+ super + 1 # override
388
+ end
389
+ end
390
+ end
391
+
392
+ # test it
393
+
394
+ AA11.new.m1.should == 2
395
+
396
+
397
+ Tag12 = Functionality do
398
+ def m1
399
+ 5 # rebase m1 again
400
+ end
401
+ end
402
+
403
+ class BB11
404
+ inject Functionality() do
405
+ def m1
406
+ super * 2 # new override
407
+ end
408
+ end
409
+ end
410
+
411
+ # test it
412
+
413
+ BB11.new.m1.should == 10
414
+
415
+
416
+ end
417
+
418
+ it 'slloed Injector Directives likr sll traits' do
419
+
420
+ Tag13 = Functionality do
421
+ def m1
422
+ 1
423
+ end
424
+ end
425
+
426
+ class AA12
427
+ inject Functionality() do
428
+ def m1
429
+ super + 1
430
+ end
431
+ end
432
+ end
433
+
434
+ AA12.new.m1.should == 2
435
+
436
+
437
+ Tag14 = Functionality do
438
+ def m1
439
+ 5 # rebase m1
440
+ end
441
+ end
442
+
443
+ class BB12
444
+ inject Functionality() do
445
+ def m1
446
+ super * 2 # new override
447
+ end
448
+ end
449
+ end
450
+
451
+ BB12.new.m1.should == 10
452
+
453
+ # test directives
454
+
455
+ Functionality(:silence)
456
+
457
+ AA12.new.m1.should == nil # both bases affected
458
+ BB12.new.m1.should == nil
459
+
460
+ Functionality(:active)
461
+
462
+ AA12.new.m1.should == 2 # both bases restored
463
+ BB12.new.m1.should == 10
464
+
465
+ end
466
+
467
+ end
468
+
469
+ describe 'jiti external basing' do
470
+
471
+ before do
472
+
473
+ #
474
+ # Injector
475
+ #
476
+ trait :Functionality
477
+
478
+ suppress_warnings do
479
+
480
+ module Base1 # EXTERNAL BASEs!!
481
+ def m1
482
+ 2
483
+ end
484
+ end
485
+
486
+ module Base2
487
+ def m1
488
+ 3
489
+ end
490
+ end
491
+
492
+ #
493
+ # Similar to Above
494
+ #
495
+ Tag1 = Functionality(Base1) do
496
+
497
+ # include Base1 # alternatively
498
+
499
+ def m2
500
+ :m2
501
+ end
502
+ end
503
+
504
+ Tag2 = Functionality do
505
+ def m1 # The :m1 override invokes JIT inheritance
506
+ super + 1 # -- Tag1 is added as ancestor
507
+ end # -- allows the use of super
508
+
509
+ def m3
510
+ 'em3'
511
+ end
512
+ end
513
+
514
+ Tag3 = Functionality() do
515
+ def m1
516
+ super * 2 # second override to #m1
517
+ end # -- Tag2 added as ancestor
518
+ def m3
519
+ super * 2 # first override to #m3
520
+ end
521
+ end
522
+
523
+ end
524
+ end
525
+
526
+ after do
527
+
528
+ suppress_warnings do
529
+
530
+ Tag1 = nil
531
+ Tag2 = nil
532
+ Tag3 = nil
533
+
534
+ end
535
+
536
+ Functionality(:implode)
537
+
538
+ end
539
+
540
+ it 'works with initial external basing' do
541
+
542
+ o = Object.new.extend(Tag3)
543
+ o.m1.should == 6 # from Base1 thru Tag3
544
+
545
+ end
546
+
547
+ it 'also keeps the main trait in sync with the last tag' do
548
+
549
+ o = Object.new.extend(Tag3)
550
+ o.m1.should == 6
551
+
552
+ p = Object.new.extend(Functionality())
553
+ p.m1.should == 6
554
+
555
+ end
556
+
557
+ it 'follows the other normal rules' do
558
+
559
+ Tag15 = Functionality do
560
+ def m1
561
+ super() * 2 # on top of Tag3
562
+ end
563
+ def m2
564
+ :m2
565
+ end
566
+ end
567
+
568
+ p = Object.new.extend(Tag15)
569
+ p.m1.should == 12
570
+
571
+ end
572
+
573
+ it 'allows external base substitution --keeps the Trait Injector shell/casing' do
574
+
575
+ q = Object.new.extend(Functionality(Base2)) # on top or Tag3 thru Tag2....
576
+ q.m1.should == 8
577
+
578
+ end
579
+
580
+ it 'also allows other external base function' do
581
+
582
+ module Base2
583
+ def m4
584
+ 'new'
585
+ end
586
+ end
587
+
588
+ Tag16 = Functionality(Base2) do
589
+ def m1
590
+ super / 2
591
+ end
592
+ def m2
593
+ super
594
+ end
595
+ end
596
+
597
+ p = Object.new.extend(Tag16)
598
+
599
+ p.m1.should == 4 # external rebase and thru Tag16, Tag3 and Tag2
600
+ p.m2.should == :m2
601
+ p.m4.should == 'new' # new function
602
+
603
+ end
604
+
605
+ it 'enforces internal basing once applied --blocks further external intrusion (like above)' do
606
+
607
+ Tag17 = Functionality(Base2) do
608
+ def m2
609
+ 6 # rebase #m2
610
+ end
611
+ end
612
+
613
+ o = Object.new.extend(Functionality())
614
+ o.m1.should == 8 # Base2 thru Tag3 casing
615
+ o.m2.should == 6 # new #m2
616
+
617
+ Functionality() do
618
+ def m1
619
+ super + 1 # on top of Tag17
620
+ end
621
+ end
622
+
623
+ p = Object.new.extend Functionality()
624
+ p.m1.should == 9
625
+
626
+ module Base3
627
+ def m1
628
+ 0 # new base
629
+ end
630
+ def m3
631
+ :m3 # muted by internal basing
632
+ end
633
+ end
634
+
635
+ p = Object.new.extend(Functionality(Base3))
636
+ p.m1.should == 3
637
+ p.m2.should == 6
638
+ p.m3.should == 'em3em3'
639
+
640
+ q = Object.new.extend(
641
+ Functionality() do
642
+ def m1
643
+ 2 # internal rebase
644
+ end
645
+ end)
646
+ q.m1.should == 2
647
+ q.m2.should == 6
648
+
649
+ Tag18 = Functionality()
650
+
651
+ module Base4
652
+ def m1
653
+ 'em1' # muted by internal rebasing
654
+ end
655
+ end
656
+
657
+ r = Object.new.extend(Functionality(Base4))
658
+ r.m1.should == 2
659
+ r.m2.should == 6
660
+
661
+ end
662
+
663
+ end