jackbox 0.9.6.6 → 0.9.6.8
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 +13 -5
- data/LICENSE.lic +0 -0
- data/LICENSE.txt +7 -1
- data/README.md +509 -406
- data/Rakefile +5 -6
- data/Vagrantfile +77 -0
- data/bin/test-jacks +13 -0
- data/jackbox.gemspec +2 -2
- data/lib/jackbox.rb +1 -1
- data/lib/jackbox/examples/dir.rb +2 -7
- data/lib/jackbox/injectors.rb +1 -1
- data/lib/jackbox/injectors/coda.rb +1 -1
- data/lib/jackbox/injectors/prelude.rb +1 -1
- data/lib/jackbox/rake.rb +1 -1
- data/lib/jackbox/tools/prefs.rb +1 -1
- data/lib/jackbox/version.rb +1 -1
- data/spec/bin/jackup_cmd_shared.rb +2 -1
- data/spec/bin/jackup_cmd_spec.rb +4 -7
- data/spec/lib/jackbox/examples/dir_spec.rb +52 -17
- data/spec/lib/jackbox/injector_composition_spec.rb +554 -85
- data/spec/lib/jackbox/injector_inheritance_spec.rb +122 -75
- data/spec/lib/jackbox/injector_introspection_spec.rb +129 -187
- data/spec/lib/jackbox/injector_namespacing_spec.rb +19 -9
- data/spec/lib/jackbox/injector_spec.rb +2 -2
- data/spec/lib/jackbox/injector_versioning_spec.rb +37 -14
- data/spec/lib/jackbox/jiti_rules_spec.rb +536 -272
- data/spec/lib/jackbox/patterns_spec.rb +142 -105
- data/spec/lib/jackbox/prefs_spec.rb +50 -39
- data/spec/lib/jackbox/vmc_spec.rb +33 -28
- data/spec/lib/jackbox_spec.rb +39 -12
- data/spec/spec_helper.rb +33 -89
- data/work +8 -0
- metadata +26 -41
@@ -256,19 +256,30 @@ end
|
|
256
256
|
|
257
257
|
describe "tag scoping and naming" do
|
258
258
|
|
259
|
-
|
259
|
+
before do
|
260
|
+
suppress_warnings do
|
261
|
+
A = Class.new
|
262
|
+
B = Class.new
|
263
|
+
end
|
264
|
+
end
|
265
|
+
after do
|
266
|
+
suppress_warnings do
|
267
|
+
A = nil
|
268
|
+
B = nil
|
269
|
+
end
|
270
|
+
end
|
271
|
+
it 'passes on top level' do
|
260
272
|
|
261
273
|
jack :M0
|
262
274
|
|
263
275
|
TopLevelTag = M0()
|
264
|
-
|
265
276
|
extend TopLevelTag
|
266
277
|
|
267
278
|
singleton_class.ancestors.to_s.should match(/TopLevelTag/)
|
268
279
|
|
269
280
|
end
|
270
281
|
|
271
|
-
it '
|
282
|
+
it 'passes for nested tags' do
|
272
283
|
|
273
284
|
module M1
|
274
285
|
jack :j1
|
@@ -278,15 +289,15 @@ describe "tag scoping and naming" do
|
|
278
289
|
Atag = M1.j1
|
279
290
|
end
|
280
291
|
|
281
|
-
class
|
292
|
+
class A
|
282
293
|
include M2::Atag
|
283
294
|
end
|
284
295
|
|
285
|
-
|
296
|
+
A.ancestors.to_s.should match(/Atag/)
|
286
297
|
|
287
298
|
end
|
288
299
|
|
289
|
-
it 'also passes' do
|
300
|
+
it 'also passes with deeper nesting' do
|
290
301
|
|
291
302
|
module M3
|
292
303
|
module M4
|
@@ -294,12 +305,11 @@ describe "tag scoping and naming" do
|
|
294
305
|
end
|
295
306
|
end
|
296
307
|
|
297
|
-
class
|
308
|
+
class B
|
298
309
|
include M3::M4::AnotherTag
|
299
310
|
end
|
300
311
|
|
301
|
-
|
302
|
-
B4.ancestors.to_s.should match(/AnotherTag/)
|
312
|
+
B.ancestors.to_s.should match(/AnotherTag/)
|
303
313
|
|
304
314
|
end
|
305
315
|
|
@@ -198,13 +198,13 @@ describe Injectors, :injectors do
|
|
198
198
|
|
199
199
|
# define more stuff on the injector
|
200
200
|
stuff do
|
201
|
-
|
201
|
+
def this_far miles
|
202
202
|
'My stuff is: ' + miles.to_s + ' miles away'
|
203
203
|
end
|
204
204
|
end
|
205
205
|
|
206
206
|
# program stiil works
|
207
|
-
some_thing.
|
207
|
+
some_thing.this_far(100).should == ('My stuff is: 100 miles away')
|
208
208
|
|
209
209
|
end
|
210
210
|
|
@@ -230,32 +230,55 @@ describe 'Injector versioning:', :traits do
|
|
230
230
|
|
231
231
|
end
|
232
232
|
|
233
|
-
there 'is a different way todo global updates on Injectors: use define_method' do
|
233
|
+
there 'is a different way todo global updates on Injectors (except for Tags): use define_method' do
|
234
234
|
|
235
|
-
SomeJack = jack :
|
235
|
+
SomeJack = jack :Some_jack do
|
236
236
|
def foo_bar
|
237
237
|
'a foo and a bar'
|
238
238
|
end
|
239
239
|
end
|
240
240
|
|
241
|
-
class
|
242
|
-
inject SomeJack
|
241
|
+
class ClientA
|
242
|
+
inject SomeJack # tag
|
243
|
+
end
|
244
|
+
class ClientB
|
245
|
+
inject Some_jack() # regular versions
|
246
|
+
end
|
247
|
+
class ClientC
|
248
|
+
inject Some_jack()
|
243
249
|
end
|
244
250
|
|
245
|
-
|
251
|
+
ClientA.new.foo_bar.should == 'a foo and a bar' # expected
|
252
|
+
ClientB.new.foo_bar.should == 'a foo and a bar' # expected
|
253
|
+
ClientC.new.foo_bar.should == 'a foo and a bar' # expected
|
246
254
|
|
247
|
-
|
255
|
+
Some_jack() do
|
248
256
|
define_method :foo_bar do
|
249
|
-
'fooooo and barrrrr'
|
257
|
+
'fooooo and barrrrr' # use #define_method
|
250
258
|
end
|
251
259
|
end
|
252
260
|
|
253
|
-
|
261
|
+
ClientA.new.foo_bar.should == 'a foo and a bar' # Tags are untouched
|
262
|
+
ClientB.new.foo_bar.should == 'fooooo and barrrrr' # changed
|
263
|
+
ClientC.new.foo_bar.should == 'fooooo and barrrrr' # changed
|
254
264
|
|
255
265
|
end
|
256
266
|
end
|
257
267
|
|
258
|
-
describe "utility of
|
268
|
+
describe "utility of injector versioning: " do
|
269
|
+
|
270
|
+
before do
|
271
|
+
suppress_warnings do
|
272
|
+
A = Class.new
|
273
|
+
B = Class.new
|
274
|
+
end
|
275
|
+
end
|
276
|
+
after do
|
277
|
+
suppress_warnings do
|
278
|
+
A = nil
|
279
|
+
B = nil
|
280
|
+
end
|
281
|
+
end
|
259
282
|
|
260
283
|
it 'allows to easily override methods without affecting other parts of your program' do
|
261
284
|
|
@@ -265,10 +288,10 @@ describe 'Injector versioning:', :traits do
|
|
265
288
|
end
|
266
289
|
end
|
267
290
|
|
268
|
-
class
|
291
|
+
class A
|
269
292
|
inject J1
|
270
293
|
end
|
271
|
-
|
294
|
+
A.new.meth(3).should == 3
|
272
295
|
|
273
296
|
J2 = j do
|
274
297
|
def meth(arg)
|
@@ -276,12 +299,12 @@ describe 'Injector versioning:', :traits do
|
|
276
299
|
end
|
277
300
|
end
|
278
301
|
|
279
|
-
class
|
302
|
+
class B
|
280
303
|
inject J2
|
281
304
|
end
|
282
|
-
|
305
|
+
B.new.meth(3).should == 9
|
283
306
|
|
284
|
-
|
307
|
+
A.new.meth(3).should == 3
|
285
308
|
|
286
309
|
end
|
287
310
|
|
@@ -1,16 +1,17 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
|
3
|
+
# RubyProf.start
|
4
|
+
|
5
|
+
describe 'jit inheriatnce with tagging' do
|
4
6
|
|
5
7
|
before do
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
trait :Functionality
|
9
|
+
#
|
10
|
+
# Trait
|
11
|
+
#
|
12
|
+
trait :Functionality
|
13
13
|
|
14
|
+
suppress_warnings do
|
14
15
|
#
|
15
16
|
# Works like class inheritance
|
16
17
|
#
|
@@ -25,11 +26,12 @@ describe 'jit inheriatnce' do
|
|
25
26
|
end
|
26
27
|
|
27
28
|
Functionality do
|
28
|
-
def other
|
29
|
-
'other'
|
30
|
-
end
|
29
|
+
def other # No overrides No inheritance
|
30
|
+
'other' # -- same ancestors as before
|
31
|
+
end # -- normal trait inheritance
|
31
32
|
end
|
32
33
|
|
34
|
+
# debugger
|
33
35
|
Tag2 = Functionality do
|
34
36
|
def m1 # The :m1 override invokes JIT inheritance
|
35
37
|
super + 1 # -- Tag1 is added as ancestor
|
@@ -40,10 +42,7 @@ describe 'jit inheriatnce' do
|
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
|
-
|
44
|
-
inject Tag2
|
45
|
-
end
|
46
|
-
|
45
|
+
# debugger
|
47
46
|
Tag3 = Functionality() do
|
48
47
|
def m1
|
49
48
|
super * 2 # second override to #m1
|
@@ -53,9 +52,10 @@ describe 'jit inheriatnce' do
|
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
A = Class.new
|
56
|
+
B = Class.new
|
57
|
+
C = Class.new
|
58
|
+
D = Class.new
|
59
59
|
|
60
60
|
end
|
61
61
|
end
|
@@ -64,9 +64,17 @@ describe 'jit inheriatnce' do
|
|
64
64
|
|
65
65
|
suppress_warnings do
|
66
66
|
|
67
|
+
A = nil
|
68
|
+
B = nil
|
69
|
+
C = nil
|
70
|
+
D = nil
|
71
|
+
|
67
72
|
Tag1 = nil
|
68
73
|
Tag2 = nil
|
69
74
|
Tag3 = nil
|
75
|
+
Tag4 = nil
|
76
|
+
Tag5 = nil
|
77
|
+
Tag6 = nil
|
70
78
|
|
71
79
|
end
|
72
80
|
|
@@ -74,7 +82,19 @@ describe 'jit inheriatnce' do
|
|
74
82
|
|
75
83
|
end
|
76
84
|
|
77
|
-
it '
|
85
|
+
it 'keeps the main trait in sync with the last tag' do
|
86
|
+
|
87
|
+
o = Object.new.extend Tag3
|
88
|
+
p = Object.new.extend Functionality()
|
89
|
+
|
90
|
+
# test it
|
91
|
+
|
92
|
+
o.m1.should == 4
|
93
|
+
p.m1.should == 4
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'works under object extension' do
|
78
98
|
|
79
99
|
o = Object.new.extend Tag3
|
80
100
|
o.m1.should == 4
|
@@ -86,18 +106,18 @@ describe 'jit inheriatnce' do
|
|
86
106
|
#
|
87
107
|
# Under Inclusion
|
88
108
|
#
|
89
|
-
class
|
109
|
+
class A
|
90
110
|
inject Tag2
|
91
111
|
end
|
92
|
-
|
112
|
+
a = A.new
|
93
113
|
|
94
114
|
# JIT inherited
|
95
|
-
|
96
|
-
|
115
|
+
a.m1.should == 2
|
116
|
+
a.m3.should == 'em3'
|
97
117
|
|
98
118
|
# Version inherited
|
99
|
-
|
100
|
-
|
119
|
+
a.m2.should == :m2
|
120
|
+
a.other.should == 'other'
|
101
121
|
|
102
122
|
Functionality().tags.should == [Tag1, Tag2, Tag3]
|
103
123
|
|
@@ -108,95 +128,64 @@ describe 'jit inheriatnce' do
|
|
108
128
|
#
|
109
129
|
# Different client/Diferent Tag
|
110
130
|
#
|
111
|
-
class
|
131
|
+
class B
|
112
132
|
inject Tag3
|
113
133
|
end
|
114
|
-
|
134
|
+
b = B.new
|
115
135
|
|
116
136
|
# JIT inherited
|
117
|
-
|
118
|
-
|
137
|
+
b.m1.should == 4
|
138
|
+
b.m3.should == 'em3em3'
|
119
139
|
|
120
140
|
# regular inheritance
|
121
|
-
|
122
|
-
|
141
|
+
b.m2.should == :m2
|
142
|
+
b.other.should == 'other'
|
123
143
|
|
124
144
|
Functionality().tags.should == [Tag1, Tag2, Tag3]
|
125
145
|
|
126
146
|
end
|
127
147
|
|
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
148
|
it 'still holds on to earlier tag definitions' do
|
172
149
|
|
150
|
+
class A
|
151
|
+
inject Tag2
|
152
|
+
end
|
153
|
+
class B
|
154
|
+
inject Tag3
|
155
|
+
end
|
173
156
|
#
|
174
157
|
# Test previous Tags are unaffected !!
|
175
158
|
#
|
176
|
-
|
177
|
-
|
178
|
-
|
159
|
+
A.new.m1.should == 2 # includes Tag2
|
160
|
+
A.new.m2.should == :m2
|
161
|
+
A.new.m3.should == 'em3'
|
179
162
|
|
180
|
-
|
181
|
-
|
182
|
-
|
163
|
+
B.new.m1.should == 4 # includes Tag3
|
164
|
+
B.new.m2.should == :m2
|
165
|
+
B.new.m3.should == 'em3em3'
|
183
166
|
|
184
167
|
#
|
185
168
|
# other clients
|
186
169
|
#
|
187
|
-
class
|
170
|
+
class C
|
188
171
|
inject Tag2
|
189
172
|
end
|
190
|
-
|
173
|
+
c = C.new
|
191
174
|
|
192
|
-
|
193
|
-
|
194
|
-
|
175
|
+
c.m1.should == 2
|
176
|
+
c.m2.should == :m2
|
177
|
+
c.m3.should == 'em3'
|
195
178
|
|
196
179
|
end
|
197
180
|
|
198
181
|
it 'keeps the VMC in proper working order' do
|
199
182
|
|
183
|
+
class A
|
184
|
+
inject Tag2
|
185
|
+
end
|
186
|
+
class B
|
187
|
+
inject Tag3
|
188
|
+
end
|
200
189
|
#
|
201
190
|
# VMC (Virtual Method Cache) method
|
202
191
|
#
|
@@ -206,24 +195,57 @@ describe 'jit inheriatnce' do
|
|
206
195
|
end
|
207
196
|
end
|
208
197
|
|
209
|
-
class
|
198
|
+
class C
|
210
199
|
inject Tag2
|
211
200
|
end
|
212
|
-
|
201
|
+
c = C.new
|
213
202
|
|
214
203
|
# jit inherited
|
215
|
-
|
216
|
-
|
204
|
+
c.m1.should == 2
|
205
|
+
c.m3.should == 'em3'
|
217
206
|
|
218
207
|
# version inherited
|
219
|
-
|
220
|
-
|
208
|
+
c.m2.should == :m2
|
209
|
+
c.other.should == 'other'
|
221
210
|
|
222
|
-
|
211
|
+
c.m4.should == :m4 # vmc method
|
223
212
|
|
224
213
|
# other clients of the VMC
|
225
|
-
|
226
|
-
|
214
|
+
A.new.m4.should == :m4
|
215
|
+
B.new.m4.should == :m4
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'allows rebasing individual methods' do
|
220
|
+
|
221
|
+
suppress_warnings do
|
222
|
+
#
|
223
|
+
# Another prolongation: back to basics
|
224
|
+
#
|
225
|
+
Tag4 = Functionality() do
|
226
|
+
def m1 # another override but no call to #super
|
227
|
+
:m1 # -- just simple override
|
228
|
+
end # -- could be tagged if needed
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# test it
|
233
|
+
|
234
|
+
o = Object.new.extend( Tag4 )
|
235
|
+
|
236
|
+
# new version of #m1 !!
|
237
|
+
o.m1.should == :m1
|
238
|
+
|
239
|
+
# JIT inherited
|
240
|
+
o.m3.should == 'em3em3' # old jiti version of m3
|
241
|
+
|
242
|
+
# Version inherited
|
243
|
+
o.m2.should == :m2 # old version of m2
|
244
|
+
o.other.should == 'other'
|
245
|
+
|
246
|
+
# Total Tags
|
247
|
+
|
248
|
+
Functionality().tags.should == [Tag1, Tag2, Tag3, Tag4]
|
227
249
|
|
228
250
|
end
|
229
251
|
|
@@ -235,31 +257,34 @@ describe 'jit inheriatnce' do
|
|
235
257
|
end
|
236
258
|
end
|
237
259
|
|
238
|
-
|
260
|
+
suppress_warnings do
|
261
|
+
Tag4 = Functionality(Mod1) do
|
239
262
|
|
240
|
-
|
263
|
+
include Mod1 # alternatively
|
241
264
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
265
|
+
def m1
|
266
|
+
super * 2
|
267
|
+
end
|
268
|
+
def m3
|
269
|
+
:m3 # m3 is rebased
|
270
|
+
end
|
271
|
+
|
247
272
|
end
|
248
273
|
end
|
249
|
-
|
274
|
+
|
250
275
|
# test it
|
251
276
|
|
252
277
|
# jit inherited
|
253
|
-
Object.new.extend(
|
254
|
-
|
255
|
-
# version inherited
|
256
|
-
Object.new.extend(
|
257
|
-
|
258
|
-
# rebased
|
259
|
-
Object.new.extend(
|
260
|
-
|
261
|
-
# ancestor injection
|
262
|
-
Object.new.extend(
|
278
|
+
Object.new.extend(Tag4).m1.should == 8 # from Tag3
|
279
|
+
|
280
|
+
# version inherited
|
281
|
+
Object.new.extend(Tag4).m2.should == :m2 # from Tag1
|
282
|
+
|
283
|
+
# rebased
|
284
|
+
Object.new.extend(Tag4).m3.should == :m3 # from Tag5
|
285
|
+
|
286
|
+
# ancestor injection
|
287
|
+
Object.new.extend(Tag4).m4.should == :m4 # from Mod1
|
263
288
|
|
264
289
|
end
|
265
290
|
|
@@ -302,34 +327,36 @@ describe 'jit inheriatnce' do
|
|
302
327
|
# Masks Ancestor intrussion
|
303
328
|
#
|
304
329
|
|
305
|
-
|
306
|
-
|
307
|
-
|
330
|
+
suppress_warnings do
|
331
|
+
Tag4 = Functionality do
|
332
|
+
def m1 # Injector has internal base method
|
333
|
+
1
|
334
|
+
end
|
308
335
|
end
|
309
|
-
end
|
310
336
|
|
311
|
-
|
312
|
-
|
313
|
-
|
337
|
+
module Mod1
|
338
|
+
def m1
|
339
|
+
'one'
|
340
|
+
end
|
314
341
|
end
|
315
|
-
end
|
316
342
|
|
317
|
-
|
343
|
+
Tag5 = Functionality(Mod1) do # Mod1 attempts to intrude on base
|
318
344
|
|
319
|
-
|
345
|
+
include Mod1
|
320
346
|
|
321
|
-
|
322
|
-
|
347
|
+
def m1
|
348
|
+
super * 2
|
349
|
+
end
|
323
350
|
end
|
324
351
|
end
|
325
|
-
|
352
|
+
|
326
353
|
# test it
|
327
354
|
|
328
|
-
o = Object.new.extend(
|
355
|
+
o = Object.new.extend(Tag5)
|
329
356
|
# jit inherited
|
330
357
|
o.m1.should == 2 # no such luck!!
|
331
358
|
|
332
|
-
p = Object.new.extend(Functionality())
|
359
|
+
p = Object.new.extend(Functionality(Mod1))
|
333
360
|
# jit inherited
|
334
361
|
p.m1.should == 2 # no such luck!!
|
335
362
|
|
@@ -341,133 +368,156 @@ describe 'jit inheriatnce' do
|
|
341
368
|
|
342
369
|
it 'allows overriding methods further down the tree' do
|
343
370
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
371
|
+
suppress_warnings do
|
372
|
+
Tag4 = Functionality do
|
373
|
+
def m1
|
374
|
+
1
|
375
|
+
end
|
376
|
+
def m2 # original definition
|
377
|
+
2
|
378
|
+
end
|
379
|
+
end
|
380
|
+
Tag5 = Functionality do
|
381
|
+
def m1
|
382
|
+
'm1'
|
383
|
+
end # skipped #m2
|
384
|
+
end
|
385
|
+
Tag6 = Functionality do
|
386
|
+
def m1
|
387
|
+
super * 2
|
388
|
+
end
|
389
|
+
def m2
|
390
|
+
super * 2 # override # m2 two levels down
|
391
|
+
end
|
392
|
+
end
|
364
393
|
end
|
365
|
-
|
366
|
-
|
394
|
+
|
395
|
+
class A
|
396
|
+
inject Tag6
|
367
397
|
end
|
368
398
|
|
369
399
|
# test it
|
370
400
|
|
371
|
-
|
372
|
-
|
401
|
+
A.new.m1.should == 'm1m1'
|
402
|
+
A.new.m2 == 4
|
373
403
|
|
374
404
|
end
|
375
405
|
|
376
406
|
it 'allows rebasing (start fresh) methods at any level' do
|
377
407
|
|
378
|
-
|
379
|
-
|
380
|
-
|
408
|
+
suppress_warnings do
|
409
|
+
Tag4 = Functionality do
|
410
|
+
def m1
|
411
|
+
1 # rebase Tag3
|
412
|
+
end
|
381
413
|
end
|
382
|
-
end
|
383
414
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
415
|
+
class A
|
416
|
+
inject Functionality() do
|
417
|
+
def m1
|
418
|
+
super + 1 # override
|
419
|
+
end
|
388
420
|
end
|
389
421
|
end
|
390
|
-
end
|
391
422
|
|
392
|
-
|
423
|
+
# test it
|
393
424
|
|
394
|
-
|
425
|
+
A.new.m1.should == 2
|
395
426
|
|
396
427
|
|
397
|
-
|
398
|
-
|
399
|
-
|
428
|
+
Tag5 = Functionality do
|
429
|
+
def m1
|
430
|
+
5 # rebase m1 again
|
431
|
+
end
|
400
432
|
end
|
401
|
-
end
|
402
433
|
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
434
|
+
class B
|
435
|
+
inject Functionality() do
|
436
|
+
def m1
|
437
|
+
super * 2 # new override
|
438
|
+
end
|
407
439
|
end
|
408
440
|
end
|
409
441
|
end
|
410
|
-
|
442
|
+
|
411
443
|
# test it
|
412
444
|
|
413
|
-
|
445
|
+
B.new.m1.should == 10
|
414
446
|
|
415
447
|
|
416
448
|
end
|
417
449
|
|
418
|
-
it '
|
450
|
+
it 'works with Trait Directives' do
|
419
451
|
|
420
|
-
|
421
|
-
|
422
|
-
|
452
|
+
suppress_warnings do
|
453
|
+
Tag4 = Functionality do
|
454
|
+
def m1
|
455
|
+
1
|
456
|
+
end
|
423
457
|
end
|
424
|
-
end
|
425
458
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
459
|
+
class A
|
460
|
+
inject Functionality() do
|
461
|
+
def m1
|
462
|
+
super + 1
|
463
|
+
end
|
430
464
|
end
|
431
465
|
end
|
432
|
-
end
|
433
466
|
|
434
|
-
|
467
|
+
A.new.m1.should == 2
|
435
468
|
|
436
469
|
|
437
|
-
|
438
|
-
|
439
|
-
|
470
|
+
Tag5 = Functionality do
|
471
|
+
def m1
|
472
|
+
5 # rebase m1
|
473
|
+
end
|
440
474
|
end
|
441
|
-
end
|
442
475
|
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
476
|
+
class B
|
477
|
+
inject Functionality() do
|
478
|
+
def m1
|
479
|
+
super * 2 # new override
|
480
|
+
end
|
447
481
|
end
|
448
482
|
end
|
449
483
|
end
|
450
|
-
|
451
|
-
|
484
|
+
|
485
|
+
B.new.m1.should == 10
|
452
486
|
|
453
487
|
# test directives
|
454
488
|
|
455
489
|
Functionality(:silence)
|
456
490
|
|
457
|
-
|
458
|
-
|
491
|
+
A.new.m1.should == nil # both bases affected
|
492
|
+
B.new.m1.should == nil
|
459
493
|
|
460
494
|
Functionality(:active)
|
461
495
|
|
462
|
-
|
463
|
-
|
496
|
+
A.new.m1.should == 2 # both bases restored
|
497
|
+
B.new.m1.should == 10
|
464
498
|
|
465
499
|
end
|
466
500
|
|
467
501
|
end
|
468
502
|
|
469
|
-
describe 'jiti external basing' do
|
470
|
-
|
503
|
+
describe 'jiti soft external basing' do
|
504
|
+
|
505
|
+
####################################################################
|
506
|
+
# Soft external basing should be the preferred way of doing things #
|
507
|
+
# . The alternative hard internal basins (see below) is not as #
|
508
|
+
# flexible and inrtoduces fixed ancestor ordering --once the #
|
509
|
+
# the ancestors are layout the keep their precedence unlsess you #
|
510
|
+
# stick only to injectors. #
|
511
|
+
# . Soft ancestors don't suffer from this like: #
|
512
|
+
# #
|
513
|
+
# trait :a, :b, :c #
|
514
|
+
# #
|
515
|
+
# x = a b c #
|
516
|
+
# y = a c b #
|
517
|
+
# @
|
518
|
+
# For more on this see the compostion spec #
|
519
|
+
# ##################################################################
|
520
|
+
|
471
521
|
before do
|
472
522
|
|
473
523
|
#
|
@@ -475,33 +525,34 @@ describe 'jiti external basing' do
|
|
475
525
|
#
|
476
526
|
trait :Functionality
|
477
527
|
|
478
|
-
suppress_warnings do
|
479
528
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
end
|
529
|
+
module Base1 # EXTERNAL BASEs!!
|
530
|
+
def m1
|
531
|
+
2
|
484
532
|
end
|
533
|
+
end
|
485
534
|
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
end
|
535
|
+
module Base2
|
536
|
+
def m1
|
537
|
+
3
|
490
538
|
end
|
539
|
+
end
|
491
540
|
|
541
|
+
suppress_warnings do
|
492
542
|
#
|
493
543
|
# Similar to Above
|
494
544
|
#
|
495
545
|
Tag1 = Functionality(Base1) do
|
496
546
|
|
497
|
-
# include Base1 #
|
547
|
+
# include Base1 # NO INTERNAL BASE!! for #m1
|
498
548
|
|
499
549
|
def m2
|
500
550
|
:m2
|
501
551
|
end
|
502
552
|
end
|
503
553
|
|
504
|
-
|
554
|
+
# debugger
|
555
|
+
Tag2 = Functionality(Base2) do
|
505
556
|
def m1 # The :m1 override invokes JIT inheritance
|
506
557
|
super + 1 # -- Tag1 is added as ancestor
|
507
558
|
end # -- allows the use of super
|
@@ -511,7 +562,8 @@ describe 'jiti external basing' do
|
|
511
562
|
end
|
512
563
|
end
|
513
564
|
|
514
|
-
|
565
|
+
# debugger
|
566
|
+
Tag3 = Functionality(Base1) do
|
515
567
|
def m1
|
516
568
|
super * 2 # second override to #m1
|
517
569
|
end # -- Tag2 added as ancestor
|
@@ -530,50 +582,66 @@ describe 'jiti external basing' do
|
|
530
582
|
Tag1 = nil
|
531
583
|
Tag2 = nil
|
532
584
|
Tag3 = nil
|
585
|
+
Tag4 = nil
|
586
|
+
Tag5 = nil
|
587
|
+
Tag6 = nil
|
533
588
|
|
534
589
|
end
|
535
590
|
|
536
591
|
Functionality(:implode)
|
537
592
|
|
538
593
|
end
|
594
|
+
|
595
|
+
it 'works for Tag1' do
|
596
|
+
|
597
|
+
o = Object.new.extend(Tag1)
|
598
|
+
o.m1.should == 2
|
599
|
+
|
600
|
+
end
|
601
|
+
|
602
|
+
it 'works for Tag2' do
|
603
|
+
|
604
|
+
o = Object.new.extend(Tag2)
|
605
|
+
o.m1.should == 4
|
606
|
+
|
607
|
+
end
|
539
608
|
|
540
609
|
it 'works with initial external basing' do
|
541
610
|
|
542
611
|
o = Object.new.extend(Tag3)
|
612
|
+
# debugger
|
543
613
|
o.m1.should == 6 # from Base1 thru Tag3
|
544
614
|
|
545
615
|
end
|
546
616
|
|
547
617
|
it 'also keeps the main trait in sync with the last tag' do
|
548
618
|
|
549
|
-
|
550
|
-
o.m1.should == 6
|
551
|
-
|
552
|
-
p = Object.new.extend(Functionality())
|
619
|
+
p = Object.new.extend(Functionality(Base1))
|
553
620
|
p.m1.should == 6
|
554
621
|
|
555
622
|
end
|
556
623
|
|
557
|
-
it '
|
624
|
+
it 'allows external base substitution --keeps the Trait Injector shell/jacket' do
|
558
625
|
|
559
|
-
|
560
|
-
|
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
|
626
|
+
q = Object.new.extend(Functionality(Base2)) # on top or Tag3 thru Tag2....
|
627
|
+
q.m1.should == 8
|
570
628
|
|
571
629
|
end
|
572
630
|
|
573
|
-
it '
|
631
|
+
it 'follows the other normal rules' do
|
574
632
|
|
575
|
-
|
576
|
-
|
633
|
+
suppress_warnings do
|
634
|
+
Tag4 = Functionality(Base1) do
|
635
|
+
def m1
|
636
|
+
super() * 2 # on top of Tag3
|
637
|
+
end
|
638
|
+
def m2
|
639
|
+
:m2
|
640
|
+
end
|
641
|
+
end
|
642
|
+
end
|
643
|
+
p = Object.new.extend(Tag4)
|
644
|
+
p.m1.should == 12
|
577
645
|
|
578
646
|
end
|
579
647
|
|
@@ -585,79 +653,275 @@ describe 'jiti external basing' do
|
|
585
653
|
end
|
586
654
|
end
|
587
655
|
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
656
|
+
suppress_warnings do
|
657
|
+
Tag4 = Functionality(Base2) do
|
658
|
+
|
659
|
+
# inject Base2
|
660
|
+
def m1
|
661
|
+
super / 2
|
662
|
+
end
|
663
|
+
def m2
|
664
|
+
super
|
665
|
+
end
|
594
666
|
end
|
595
667
|
end
|
596
|
-
|
597
|
-
p = Object.new.extend(
|
668
|
+
# p = Object.new.extend(Tag4, Base2)
|
669
|
+
p = Object.new.extend(Tag4)
|
598
670
|
|
599
671
|
p.m1.should == 4 # external rebase and thru Tag16, Tag3 and Tag2
|
600
672
|
p.m2.should == :m2
|
601
673
|
p.m4.should == 'new' # new function
|
674
|
+
|
675
|
+
module Base3
|
676
|
+
def m1
|
677
|
+
5
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
suppress_warnings do
|
682
|
+
Tag5 = Functionality(Base3) do
|
683
|
+
|
684
|
+
# inject Base3
|
685
|
+
def m1
|
686
|
+
super + 1
|
687
|
+
end
|
688
|
+
end
|
689
|
+
end
|
690
|
+
# q = Object.new.extend(Tag5, Base3)
|
691
|
+
q = Object.new.extend(Tag5)
|
692
|
+
|
693
|
+
# debugger
|
694
|
+
q.m1.should == 7
|
602
695
|
|
603
696
|
end
|
604
697
|
|
605
698
|
it 'enforces internal basing once applied --blocks further external intrusion (like above)' do
|
606
699
|
|
607
|
-
|
608
|
-
|
609
|
-
|
700
|
+
suppress_warnings do
|
701
|
+
Tag4 = Functionality() do
|
702
|
+
# ... # on top of Tag3
|
703
|
+
def m2
|
704
|
+
6 # rebase #m2
|
705
|
+
end
|
610
706
|
end
|
611
|
-
|
707
|
+
o = Object.new.extend(Functionality(Base2))
|
708
|
+
|
709
|
+
o.m1.should == 8
|
710
|
+
o.m2.should == 6
|
612
711
|
|
613
|
-
|
614
|
-
|
615
|
-
|
712
|
+
Functionality() do
|
713
|
+
def m1
|
714
|
+
super + 1 # thru Tag4 on top of Tag3
|
715
|
+
end
|
716
|
+
end
|
717
|
+
p = Object.new.extend Functionality(Base2)
|
616
718
|
|
617
|
-
|
618
|
-
|
619
|
-
|
719
|
+
p.m1.should == 9
|
720
|
+
p.m2.should == 6
|
721
|
+
|
722
|
+
|
723
|
+
module Base3 # EXTERNAL NEW BASE!!
|
724
|
+
def m1
|
725
|
+
0 # rebase #m1
|
726
|
+
end
|
727
|
+
def m3
|
728
|
+
:m3 # muted by internal basing
|
729
|
+
end
|
620
730
|
end
|
731
|
+
p = Object.new.extend(Functionality(Base3))
|
732
|
+
|
733
|
+
p.m1.should == 3
|
734
|
+
p.m2.should == 6
|
735
|
+
p.m3.should == 'em3em3'
|
736
|
+
|
737
|
+
|
738
|
+
q = Object.new.extend( # INTERNAL NEW BASE!!
|
739
|
+
Functionality() do
|
740
|
+
def m1
|
741
|
+
2 # internal rebase blocks outside one
|
742
|
+
end
|
743
|
+
end)
|
744
|
+
|
745
|
+
q.m1.should == 2
|
746
|
+
q.m2.should == 6
|
747
|
+
|
748
|
+
module Base4 # EXTERNAL NEW BASE
|
749
|
+
def m1
|
750
|
+
'em1' # muted by internal rebasing
|
751
|
+
end
|
752
|
+
end
|
753
|
+
r = Object.new.extend(Functionality(Base4))
|
754
|
+
|
755
|
+
r.m1.should == 2
|
756
|
+
r.m2.should == 6
|
621
757
|
end
|
622
758
|
|
623
|
-
|
624
|
-
|
759
|
+
end
|
760
|
+
|
761
|
+
end
|
625
762
|
|
626
|
-
|
763
|
+
describe 'jiti hard external basing' do
|
764
|
+
|
765
|
+
####################################################################
|
766
|
+
# Soft external basing should be the preferred way of doing things #
|
767
|
+
# . The alternative hard internal basing (see below) is not as #
|
768
|
+
# flexible and inrtoduces fixed ancestor ordering --once the #
|
769
|
+
# the ancestors are layout the keep their precedence unlsess you #
|
770
|
+
# stick only to injectors. #
|
771
|
+
# . Soft ancestors don't suffer from this like: #
|
772
|
+
# #
|
773
|
+
# trait :a, :b, :c #
|
774
|
+
# #
|
775
|
+
# x = a b c #
|
776
|
+
# y = a c b #
|
777
|
+
# @
|
778
|
+
# For more on this see the compostion spec #
|
779
|
+
# ##################################################################
|
780
|
+
|
781
|
+
before do
|
782
|
+
|
783
|
+
#
|
784
|
+
# Injector
|
785
|
+
#
|
786
|
+
trait :Functionality
|
787
|
+
|
788
|
+
|
789
|
+
module Base1 # EXTERNAL BASEs!!
|
627
790
|
def m1
|
628
|
-
|
791
|
+
2
|
629
792
|
end
|
630
|
-
|
631
|
-
|
793
|
+
end
|
794
|
+
|
795
|
+
module Base2
|
796
|
+
def m1
|
797
|
+
3
|
632
798
|
end
|
633
799
|
end
|
634
800
|
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
801
|
+
suppress_warnings do
|
802
|
+
#
|
803
|
+
# Similar to Above
|
804
|
+
#
|
805
|
+
Tag1 = Functionality() do
|
806
|
+
|
807
|
+
include Base1 # SAME AS AN INTERNAL BASE PRACTICALLY!!
|
639
808
|
|
640
|
-
|
641
|
-
|
642
|
-
def m1
|
643
|
-
2 # internal rebase
|
809
|
+
def m2
|
810
|
+
:m2
|
644
811
|
end
|
645
|
-
end
|
646
|
-
|
647
|
-
|
812
|
+
end
|
813
|
+
|
814
|
+
Tag2 = Functionality() do
|
815
|
+
|
816
|
+
include Base2
|
817
|
+
|
818
|
+
def m1 # The :m1 override invokes JIT inheritance
|
819
|
+
super + 1 # -- Tag1 is added as ancestor
|
820
|
+
end # -- allows the use of super
|
821
|
+
|
822
|
+
def m3
|
823
|
+
'em3'
|
824
|
+
end
|
825
|
+
end
|
826
|
+
|
827
|
+
Tag3 = Functionality() do
|
828
|
+
|
829
|
+
include Base1 # THIS DOESN'T WORK!!!
|
830
|
+
# Base1 was already an ancestor before Base2
|
831
|
+
def m1
|
832
|
+
super * 2 # second override to #m1
|
833
|
+
end # -- Tag2 added as ancestor
|
834
|
+
def m3
|
835
|
+
super * 2 # first override to #m3
|
836
|
+
end
|
837
|
+
end
|
838
|
+
|
839
|
+
end
|
840
|
+
end
|
841
|
+
|
842
|
+
after do
|
843
|
+
|
844
|
+
suppress_warnings do
|
845
|
+
|
846
|
+
Tag1 = nil
|
847
|
+
Tag2 = nil
|
848
|
+
Tag3 = nil
|
849
|
+
Tag4 = nil
|
850
|
+
Tag5 = nil
|
851
|
+
Tag6 = nil
|
852
|
+
|
853
|
+
end
|
854
|
+
|
855
|
+
Functionality(:implode)
|
856
|
+
|
857
|
+
end
|
858
|
+
|
859
|
+
it 'works for Tag1' do
|
648
860
|
|
649
|
-
|
861
|
+
# SAME AS ABOVE
|
650
862
|
|
651
|
-
|
652
|
-
|
653
|
-
|
863
|
+
o = Object.new.extend(Tag1)
|
864
|
+
o.m1.should == 2
|
865
|
+
|
866
|
+
end
|
867
|
+
|
868
|
+
it 'works for Tag2' do
|
869
|
+
|
870
|
+
# SAME AS ABOVE
|
871
|
+
|
872
|
+
o = Object.new.extend(Tag2)
|
873
|
+
o.m1.should == 4
|
874
|
+
|
875
|
+
end
|
876
|
+
|
877
|
+
it 'works with initial external basing' do
|
878
|
+
|
879
|
+
# DIFFERENT THAN ABOVE
|
880
|
+
|
881
|
+
o = Object.new.extend(Tag3)
|
882
|
+
o.m1.should == 8
|
883
|
+
|
884
|
+
end
|
885
|
+
|
886
|
+
it 'also keeps the main trait in sync with the last tag' do
|
887
|
+
|
888
|
+
# SAME AS ABOVE
|
889
|
+
|
890
|
+
p = Object.new.extend(Functionality(Base1)) # THIS DOESN'T WORK EITHER!!!
|
891
|
+
p.m1.should == 8
|
892
|
+
|
893
|
+
end
|
894
|
+
|
895
|
+
it 'allows external base substitution --keeps the Trait Injector shell/jacket' do
|
896
|
+
|
897
|
+
# SAME AS ABOVE
|
898
|
+
|
899
|
+
q = Object.new.extend(Functionality()) # Base2 comming from internal spec!!!!
|
900
|
+
q.m1.should == 8
|
901
|
+
|
902
|
+
end
|
903
|
+
|
904
|
+
it 'follows the other normal rules' do
|
905
|
+
|
906
|
+
# DIFFERENT THAN ABOVE
|
907
|
+
|
908
|
+
suppress_warnings do
|
909
|
+
Tag4 = Functionality(Base1) do # THIS DOESN'T WORK EITHER!!!
|
910
|
+
def m1
|
911
|
+
super() * 2
|
912
|
+
end
|
913
|
+
def m2
|
914
|
+
:m2
|
915
|
+
end
|
654
916
|
end
|
655
917
|
end
|
656
|
-
|
657
|
-
|
658
|
-
r.m1.should == 2
|
659
|
-
r.m2.should == 6
|
918
|
+
p = Object.new.extend(Tag4)
|
919
|
+
p.m1.should == 16
|
660
920
|
|
661
921
|
end
|
662
922
|
|
663
923
|
end
|
924
|
+
# profile = RubyProf.stop
|
925
|
+
# RubyProf::FlatPrinter.new(profile).print(STDOUT)
|
926
|
+
# RubyProf::GraphHtmlPrinter.new(profile).print(open('profile.html', 'w+'))
|
927
|
+
# RubyProf::CallStackPrinter.new(profile).print(open('profile.html', 'w+'))
|