jackbox 0.9.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +5 -0
  3. data/CHANGES.txt +108 -0
  4. data/LICENSE.lic +0 -0
  5. data/LICENSE.txt +13 -0
  6. data/README.md +1395 -0
  7. data/Rakefile +6 -0
  8. data/bin/jackup +248 -0
  9. data/jackbox.gemspec +27 -0
  10. data/jackbox.jpg +0 -0
  11. data/lib/.document +0 -0
  12. data/lib/jackbox.rb +2 -0
  13. data/lib/jackbox/examples/dir.rb +80 -0
  14. data/lib/jackbox/examples/dx.rb +182 -0
  15. data/lib/jackbox/examples/transformers.rb +101 -0
  16. data/lib/jackbox/injectors.rb +2 -0
  17. data/lib/jackbox/rake.rb +2 -0
  18. data/lib/jackbox/tools/prefs.rb +2 -0
  19. data/lib/jackbox/version.rb +4 -0
  20. data/rgloader/loader.rb +23 -0
  21. data/rgloader/rgloader.darwin.bundle +0 -0
  22. data/rgloader/rgloader.freebsd.so +0 -0
  23. data/rgloader/rgloader.freebsd.x86_64.so +0 -0
  24. data/rgloader/rgloader.linux.so +0 -0
  25. data/rgloader/rgloader.linux.x86_64.so +0 -0
  26. data/rgloader/rgloader.mingw.so +0 -0
  27. data/rgloader/rgloader19.darwin.bundle +0 -0
  28. data/rgloader/rgloader19.freebsd.so +0 -0
  29. data/rgloader/rgloader19.freebsd.x86_64.so +0 -0
  30. data/rgloader/rgloader19.linux.so +0 -0
  31. data/rgloader/rgloader19.linux.x86_64.so +0 -0
  32. data/rgloader/rgloader19.mingw.so +0 -0
  33. data/rgloader/rgloader191.mingw.so +0 -0
  34. data/rgloader/rgloader192.darwin.bundle +0 -0
  35. data/rgloader/rgloader192.freebsd.so +0 -0
  36. data/rgloader/rgloader192.freebsd.x86_64.so +0 -0
  37. data/rgloader/rgloader192.linux.so +0 -0
  38. data/rgloader/rgloader192.linux.x86_64.so +0 -0
  39. data/rgloader/rgloader192.mingw.so +0 -0
  40. data/rgloader/rgloader193.darwin.bundle +0 -0
  41. data/rgloader/rgloader193.freebsd.so +0 -0
  42. data/rgloader/rgloader193.freebsd.x86_64.so +0 -0
  43. data/rgloader/rgloader193.linux.so +0 -0
  44. data/rgloader/rgloader193.linux.x86_64.so +0 -0
  45. data/rgloader/rgloader193.mingw.so +0 -0
  46. data/rgloader/rgloader20.darwin.bundle +0 -0
  47. data/rgloader/rgloader20.freebsd.so +0 -0
  48. data/rgloader/rgloader20.freebsd.x86_64.so +0 -0
  49. data/rgloader/rgloader20.linux.so +0 -0
  50. data/rgloader/rgloader20.linux.x86_64.so +0 -0
  51. data/rgloader/rgloader20.mingw.so +0 -0
  52. data/rgloader/rgloader20.mingw.x64.so +0 -0
  53. data/rgloader/rgloader21.darwin.bundle +0 -0
  54. data/rgloader/rgloader21.freebsd.so +0 -0
  55. data/rgloader/rgloader21.freebsd.x86_64.so +0 -0
  56. data/rgloader/rgloader21.linux.so +0 -0
  57. data/rgloader/rgloader21.linux.x86_64.so +0 -0
  58. data/rgloader/rgloader21.mingw.so +0 -0
  59. data/rgloader/rgloader21.mingw.x64.so +0 -0
  60. data/rgloader/rgloader22.darwin.bundle +0 -0
  61. data/rgloader/rgloader22.freebsd.so +0 -0
  62. data/rgloader/rgloader22.linux.so +0 -0
  63. data/rgloader/rgloader22.linux.x86_64.so +0 -0
  64. data/rgloader/rgloader22.mingw.so +0 -0
  65. data/rgloader/rgloader22.mingw.x64.so +0 -0
  66. data/spec/bin/jackup_cmd_shared.rb +176 -0
  67. data/spec/bin/jackup_cmd_spec.rb +292 -0
  68. data/spec/lib/abtract_spec.rb +56 -0
  69. data/spec/lib/jackbox/examples/dir_spec.rb +112 -0
  70. data/spec/lib/jackbox/examples/dx_spec.rb +346 -0
  71. data/spec/lib/jackbox/examples/result.xml +15 -0
  72. data/spec/lib/jackbox/examples/source1.xml +11 -0
  73. data/spec/lib/jackbox/examples/source2.xml +15 -0
  74. data/spec/lib/jackbox/examples/source3.xml +11 -0
  75. data/spec/lib/jackbox/examples/trasnformers_spec.rb +35 -0
  76. data/spec/lib/jackbox/injector_composition_spec.rb +950 -0
  77. data/spec/lib/jackbox/injector_directives_spec.rb +266 -0
  78. data/spec/lib/jackbox/injector_inheritance_spec.rb +799 -0
  79. data/spec/lib/jackbox/injector_introspection_spec.rb +614 -0
  80. data/spec/lib/jackbox/injector_namespacing_spec.rb +345 -0
  81. data/spec/lib/jackbox/injector_spec.rb +847 -0
  82. data/spec/lib/jackbox/injector_versioning_spec.rb +334 -0
  83. data/spec/lib/jackbox/patterns_spec.rb +410 -0
  84. data/spec/lib/jackbox/prefs_spec.rb +212 -0
  85. data/spec/lib/jackbox/reclassing_spec.rb +394 -0
  86. data/spec/lib/jackbox_spec.rb +595 -0
  87. data/spec/spec_helper.rb +139 -0
  88. metadata +218 -0
@@ -0,0 +1,334 @@
1
+ require "spec_helper"
2
+
3
+ include Injectors
4
+
5
+ describe 'Injector versioning:', :injectors do
6
+ # subsequent redefinitions of methods constitute another version of the injector. Injector
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
11
+ # of the object of injection unless some form of reinjection occurs. Newer versions of methods only become part of newer
12
+ # objects or newer injections into existing targets'
13
+
14
+ describe 'injector versioning and its relationship to object instances' do
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
19
+ # may contain internal references to newer versions of the target methods. This ensures to keep everyting working correctly.'
20
+
21
+ #___________________
22
+ # injector declaration
23
+ injector :My_injector
24
+
25
+ #___________________
26
+ # injector first prolongation
27
+ My_injector do
28
+ def bar
29
+ :a_bar # version bar.1
30
+ end
31
+ def foo
32
+ # ...
33
+ end
34
+ end
35
+
36
+ object1 = Object.new
37
+ object1.enrich My_injector() # apply the injector --first snapshot
38
+ object1.bar.should == :a_bar # pass the test
39
+
40
+ #__________________
41
+ # injector second prolongation
42
+ My_injector do
43
+ def bar
44
+ :some_larger_bar # version bar.2 ... re-defines bar
45
+ end
46
+ def some_other_function
47
+ # ...
48
+ end
49
+ end
50
+
51
+ object2 = Object.new
52
+ object2.enrich My_injector() # apply the injector --second snapshot
53
+ object2.bar.should == :some_larger_bar
54
+
55
+ # result
56
+ ###########
57
+
58
+ object1.bar.should == :a_bar # bar.1 is still the one
59
+
60
+ ###########################################
61
+ # The object has kept its preferred version
62
+
63
+ end
64
+
65
+ the 're-injection changes ("updates if you will") versions of methods in use' do
66
+
67
+ #_________________
68
+ # re-injection
69
+ enrich My_injector() # re-injection on any object instance
70
+ bar.should == :some_larger_bar # bar.2 now available
71
+
72
+ expect{some_other_function}.to_not raise_error # some_other_function.1 is present
73
+
74
+ end
75
+
76
+ a 'different example with an explicit self' do
77
+
78
+ o = Object.new
79
+
80
+ injector :some_methods do
81
+ def meth arg
82
+ arg
83
+ end
84
+ end
85
+
86
+ o.enrich some_methods
87
+ o.meth('cha cha').should == 'cha cha'
88
+
89
+ some_methods do
90
+ def meth arg
91
+ arg * 2
92
+ end
93
+ end
94
+
95
+ o.meth('cha cha').should == 'cha cha'
96
+
97
+ oo = Object.new.enrich(some_methods)
98
+ oo.meth('cha cha').should == 'cha cha'+'cha cha'
99
+
100
+ o.meth('cha cha').should == 'cha cha'
101
+
102
+ end
103
+
104
+ end
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
108
+ # that version of methods as the object of injection. But, unlike object level versioning, because class injection is static, reinjection
109
+ # does not change the class unless we use the Strategy Pattern which completely changes the class's strategy of methods"
110
+
111
+ the "class injector versioning is similar to object injector versioning" do
112
+
113
+ #___________________
114
+ # injector declaration:
115
+ injector :Versions
116
+
117
+ #___________________
118
+ # injector first prolongation
119
+ Version1 = Versions do
120
+ def meth arg # version meth.1
121
+ arg ** arg
122
+ end
123
+ end
124
+
125
+ class One
126
+ inject Version1 # apply --first snapshot
127
+ end
128
+
129
+ #_________________
130
+ # injector second prolongation
131
+ Version2 = Versions do
132
+ def meth arg1, arg2 # version meth.2 ... redefines meth.1
133
+ arg1 * arg2
134
+ end
135
+ end
136
+
137
+ class Two
138
+ inject Version2 # apply --second snapshot
139
+ end
140
+
141
+
142
+ # result
143
+ #############################
144
+ Two.new.meth(2,4).should == 8 # meth.2
145
+ # two different injector versions
146
+ One.new.meth(3).should == 27 # meth.1
147
+ #############################
148
+ #
149
+
150
+ end
151
+
152
+ # we can update individual object instances but not classes directly
153
+ # this is unavailable because class injection is pervasive
154
+ the 'simple re-injection is different for classes: it fails ' do
155
+
156
+ # re-injection can happen on individual object instances
157
+ One.new.enrich(Version2).meth(4,5).should == 20 # meth.2 works!!
158
+
159
+ # re-injection applying version 2 to class One has no effect
160
+ One.inject Version2
161
+ expect{ One.new.meth(4,5) }.to raise_error(ArgumentError) # meth.2: fails!!
162
+
163
+ end
164
+
165
+ the 'way to class level injector updates is through the Strategy Pattern' do
166
+
167
+ # DO NOT want to necessarily update older clients of the class
168
+ # but possible if needed
169
+
170
+ class One
171
+ eject Version1 # eject version 1
172
+
173
+ inject Version2 # re-inject with prolonged injector -- can be any version
174
+ end
175
+ One.new.meth(4,5).should == 20 # meth.2 now available!!
176
+
177
+ ################################################
178
+ # We feel this is the correct approach but has #
179
+ # a sllight syntactical handicap/ambiguity #
180
+ ################################################
181
+
182
+ end
183
+
184
+ a 'preferred way as of late: private updates --could change' do
185
+
186
+ Versions do
187
+ def meth(*args)
188
+ args.inject(&:+)
189
+ end
190
+ end
191
+
192
+ class One
193
+ update Versions() # changes strategy for you
194
+ # by design a private method as sign of its delicate nature
195
+ end
196
+
197
+ # or ....
198
+
199
+ One.send :update, Versions()
200
+ One.new.meth( 3,4,5,6 ).should == 18 # new version now available!
201
+
202
+ end
203
+
204
+ a 'different use case' do
205
+
206
+ class Freak
207
+
208
+ injector :freaky
209
+ freaky do
210
+ def twitch
211
+ '_-=-_-=-_-=-_-=-_'
212
+ end
213
+ end
214
+ inject freaky
215
+
216
+ end
217
+ Freak.new.twitch.should == '_-=-_-=-_-=-_-=-_'
218
+
219
+ class Freak
220
+
221
+ freaky do
222
+ def twitch
223
+ '/\/\/\/\/\/\/\/\/\/'
224
+ end
225
+ end
226
+ update freaky
227
+
228
+ end
229
+ Freak.new.twitch.should == '/\/\/\/\/\/\/\/\/\/'
230
+
231
+ end
232
+
233
+ there 'is a different way todo global updates on Injectors: use define_method' do
234
+
235
+ SomeJack = jack :some_jack do
236
+ def foo_bar
237
+ 'a foo and a bar'
238
+ end
239
+ end
240
+
241
+ class Client
242
+ inject SomeJack
243
+ end
244
+
245
+ Client.new.foo_bar.should == 'a foo and a bar' # expected
246
+
247
+ some_jack do
248
+ define_method :foo_bar do
249
+ 'fooooo and barrrrr'
250
+ end
251
+ end
252
+
253
+ Client.new.foo_bar.should == 'fooooo and barrrrr' # different
254
+
255
+ end
256
+ end
257
+
258
+ describe "utility of injector versioning: " do
259
+
260
+ it 'allows to easily override methods without affecting other parts of your program' do
261
+
262
+ J1 = injector :j do
263
+ def meth(arg)
264
+ arg
265
+ end
266
+ end
267
+
268
+ class AA4
269
+ inject J1
270
+ end
271
+ AA4.new.meth(3).should == 3
272
+
273
+ J2 = j do
274
+ def meth(arg)
275
+ arg *arg
276
+ end
277
+ end
278
+
279
+ class BBB
280
+ inject J2
281
+ end
282
+ BBB.new.meth(3).should == 9
283
+
284
+ AA4.new.meth(3).should == 3
285
+
286
+ end
287
+
288
+ the "local binding of injectors" do
289
+
290
+ #_____________________
291
+ # injector declaration
292
+ VersionOne = injector :functionality do
293
+ def basic arg # version basic.1
294
+ arg * 2
295
+ end
296
+ end
297
+
298
+ o = Object.new.enrich VersionOne # apply --first snapshot
299
+ o.basic(1).should == 2 # basic.1
300
+
301
+
302
+ #_____________________
303
+ # injector prolongation
304
+ VersionTwo = functionality do
305
+ def basic arg # basic.2 ... basic.1 redefined
306
+ arg * 3
307
+ end
308
+
309
+ def compound # compound.1 --bound locally to basic.2
310
+ basic(3) + 2
311
+ end
312
+ end
313
+
314
+ p = Object.new.enrich VersionTwo # apply --second snapshot (like above)
315
+ p.basic(1).should == 3 # basic.2
316
+ p.compound.should == 11 # compound.1
317
+
318
+
319
+ # result
320
+ ###################################
321
+
322
+ o.basic(1).should == 2 # basic.1
323
+ o.compound.should == 11 # compound.1 --local injector binding
324
+
325
+ ###################################
326
+ # This ensures #compound.1 keeps bound
327
+ # to the right version #basic.2
328
+
329
+ end
330
+
331
+ end
332
+ end
333
+
334
+
@@ -0,0 +1,410 @@
1
+ require "spec_helper"
2
+ =begin rdoc
3
+ This file contains the specs for the GOF Decorator Pattern and
4
+ Strategy Pattern use cases for injectors.
5
+ =end
6
+
7
+ include Injectors
8
+
9
+ describe 'some use cases', :injectors do
10
+
11
+ describe 'GOF Decortors is one use of this codebase. Traditionally this is only partially solved in Ruby through PORO
12
+ decorators or the use of modules with the problems of loss of class identity for the former
13
+ or the limitations on the times it can be re-applied for the latter. We solve that!!' do
14
+
15
+ the 'GOF class decorator' do
16
+
17
+ class Coffee
18
+ def cost
19
+ 1.50
20
+ end
21
+ end
22
+
23
+ injector :milk do
24
+ def cost
25
+ super() + 0.30
26
+ end
27
+ end
28
+ injector :vanilla do
29
+ def cost
30
+ super() + 0.15
31
+ end
32
+ end
33
+
34
+ cup = Coffee.new.enrich(milk).enrich(vanilla)
35
+ cup.should be_instance_of(Coffee)
36
+ cup.cost.should == 1.95
37
+
38
+ end
39
+
40
+ this 'can then be applied multiple times to the same receiver:' do
41
+
42
+ class Coffee
43
+ def cost
44
+ 1.50
45
+ end
46
+ end
47
+
48
+ jack :milk do
49
+ def cost
50
+ super() + 0.30
51
+ end
52
+ end
53
+ jack :vanilla do
54
+ def cost
55
+ super() + 0.15
56
+ end
57
+ end
58
+
59
+ cup = Coffee.new.enrich(milk).enrich(vanilla).enrich(vanilla)
60
+ cup.injectors.sym_list.should == [:milk, :vanilla, :vanilla]
61
+ cup.cost.should == 2.10
62
+ cup.should be_instance_of(Coffee)
63
+
64
+ end
65
+
66
+ the 'a further workflow' do
67
+
68
+ class Coffee
69
+ def cost
70
+ 1.50
71
+ end
72
+ end
73
+
74
+ jack :milk do
75
+ def cost
76
+ super() + 0.30
77
+ end
78
+ end
79
+ jack :vanilla do
80
+ def cost
81
+ super() + 0.15
82
+ end
83
+ end
84
+
85
+ cup = Coffee.new.enrich(milk).enrich(vanilla)
86
+ cup.should be_instance_of(Coffee)
87
+ cup.cost.should == 1.95
88
+
89
+ user_input = 'extra red vanilla'
90
+ vanilla do
91
+ define_method :appearance do
92
+ user_input
93
+ end
94
+ end
95
+
96
+ cup.enrich(vanilla)
97
+ cup.injectors.sym_list.should == [:milk, :vanilla, :vanilla]
98
+ cup.cost.should == 2.10
99
+ cup.appearance.should == 'extra red vanilla'
100
+
101
+ end
102
+
103
+ a 'bigger example' do
104
+
105
+ # some data
106
+
107
+ def database_content
108
+ %{car truck airplane boat}
109
+ end
110
+
111
+ # rendering helper controls
112
+
113
+ class MyWidgetClass
114
+ def initialize(content)
115
+ @content = content
116
+ end
117
+
118
+ def render
119
+ "<div id='MyWidget'>#{@content}</div>"
120
+ end
121
+ end
122
+
123
+ injector :WidgetDecorator do
124
+ attr_reader :width, :height
125
+
126
+ def dim(width, heigth)
127
+ @width, @heigth = width, heigth
128
+ end
129
+ end
130
+
131
+ DesktopDecorator = WidgetDecorator do
132
+ def render
133
+ dim '600px', '200px'
134
+ %{
135
+ <style>
136
+ #MyWidget{
137
+ font: 14px, helvetica;
138
+ width:#{@width};
139
+ height: #{@heigth}
140
+ }
141
+ </style>
142
+ #{super()}
143
+ }
144
+ end
145
+ end
146
+
147
+ MobileDecorator = WidgetDecorator do
148
+ def render content
149
+ dim '200px', '600px'
150
+ %{
151
+ <style>
152
+ #MyWidget{
153
+ font: 10px, arial
154
+ width:#{@width}
155
+ height: #{@heigth}
156
+ }
157
+ </style>
158
+ #{super()}
159
+ }
160
+ end
161
+ end
162
+
163
+
164
+ # somewhere in a view
165
+
166
+ browser = 'Safari'
167
+ @content = database_content
168
+
169
+ my_widget = case browser
170
+ when match(/Safari|Firefox|IE/)
171
+ MyWidgetClass.new(@content).enrich(DesktopDecorator)
172
+ else
173
+ MyWidgetClass.new(@content).enrich(MobileDecorator)
174
+ end
175
+ expect(
176
+
177
+ my_widget.render.split.join).to eq( # split.join used for comparison
178
+ %{
179
+ <style>
180
+ #MyWidget {
181
+ font: 14px, helvetica;
182
+ width:600px;
183
+ height:200px
184
+ }
185
+ </style>
186
+ <div id='MyWidget'>car truck airplane boat</div>
187
+ }.split.join
188
+ )
189
+
190
+ end
191
+
192
+ end
193
+
194
+ describe 'strategy pattern.' do
195
+
196
+ this 'is a pattern with changes the guts of an object as opposed to just changing its face. Traditional
197
+ examples of this pattern use PORO component injection within constructors. Here is an alternate
198
+ implementation' do
199
+
200
+ class Coffee
201
+
202
+ attr_reader :strategy
203
+ def initialize
204
+ @strategy = nil
205
+ end
206
+ def cost
207
+ 1.50
208
+ end
209
+ def brew
210
+ @strategy = 'normal-'
211
+ end
212
+ end
213
+
214
+ injector :Sweedish do
215
+ def brew
216
+ @strategy = 'sweedish-'
217
+ end
218
+ end
219
+ injector :French do
220
+ def brew
221
+ @strategy ='french-'
222
+ end
223
+ end
224
+
225
+ cup = Coffee.new
226
+ cup.brew
227
+ cup.strategy.should == 'normal-'
228
+
229
+ cup = Coffee.new.enrich(Sweedish()) # clobbers original strategy for this instance only
230
+ cup.brew
231
+ cup.strategy.should == ('sweedish-')
232
+
233
+ cup.enrich(French())
234
+ cup.brew
235
+ cup.strategy.should == ('french-')
236
+ end
237
+
238
+ this 'can be further enhanced by mixing it with the above decorator pattern' do
239
+
240
+ injector :Russian do
241
+ def brew
242
+ @strategy = super.to_s + 'vodka-'
243
+ end
244
+ end
245
+ injector :Scotish do
246
+ def brew
247
+ @strategy = super.to_s + 'wiskey-'
248
+ end
249
+ end
250
+
251
+ cup = Coffee.new
252
+ cup.enrich(Russian()).enrich(Scotish()).enrich(Russian())
253
+ cup.brew
254
+ cup.strategy.should == 'normal-vodka-wiskey-vodka-'
255
+
256
+ end
257
+
258
+ it 'is even better or possible to have yet another implementation. This time we completely
259
+ replace the current strategy by actually ejecting it out of the class and then injecting
260
+ a new one' do
261
+
262
+ class Tea < Coffee # Tea is a type of coffee ;~Q)
263
+ injector :SpecialStrategy do
264
+ def brew
265
+ @strategy = 'special'
266
+ end
267
+ end
268
+ inject SpecialStrategy()
269
+ end
270
+
271
+ cup = Tea.new
272
+ cup.brew
273
+ cup.strategy.should == 'special'
274
+ friends_cup = Tea.new
275
+ friends_cup.strategy == 'special'
276
+
277
+ Tea.eject :SpecialStrategy
278
+
279
+ Tea.inject Sweedish()
280
+ cup.brew
281
+ friends_cup.brew
282
+ cup.strategy.should == 'sweedish-'
283
+ friends_cup.strategy.should == 'sweedish-'
284
+
285
+ Tea.eject Sweedish()
286
+
287
+ Tea.inject French()
288
+ cup.brew
289
+ friends_cup.brew
290
+ cup.strategy == 'french-'
291
+ friends_cup.strategy.should == 'french-'
292
+
293
+ end
294
+
295
+ end
296
+
297
+ describe "further Jackbox Injector workflows" do
298
+
299
+ it "allows adding decorators with function to be defined at later statge" do
300
+
301
+ class Widget
302
+ def cost
303
+ 1
304
+ end
305
+ end
306
+ w = Widget.new
307
+
308
+ injector :decorator
309
+ w.enrich decorator, decorator, decorator, decorator
310
+
311
+ # user input
312
+ bid = 3.5
313
+
314
+ # define function
315
+ decorator do
316
+ # Global define
317
+ define_method :cost do
318
+ super() + bid
319
+ end
320
+ end
321
+
322
+ w.cost.should == 15
323
+
324
+ end
325
+
326
+ it "allows for the following workflow using super" do
327
+
328
+ jack :Superb
329
+
330
+ Superb do
331
+ def process string, additives, index
332
+ str = string.gsub('o', additives.slice!(index))
333
+ super(string, additives, index) + str rescue str
334
+ end
335
+ extend Superb(), Superb(), Superb()
336
+ end
337
+
338
+ Superb().process( 'food ', 'aeiu', 0 ).should == 'fuud fiid feed faad '
339
+ Superb(:implode)
340
+
341
+ end
342
+
343
+ it 'allows for the following strategy workflow using soft tags' do
344
+
345
+ ###########################################################################
346
+ # For a specific example of what can be accomplished using this workflow #
347
+ # please refer to the examples directory under transformers spec #
348
+ # #
349
+ # #########################################################################
350
+
351
+ jack :Solution
352
+
353
+ Solution( :tag ) do
354
+ def solution
355
+ 1
356
+ end
357
+ end
358
+ Solution( :tag ) do
359
+ def solution
360
+ 2
361
+ end
362
+ end
363
+ Solution( :tag ) do
364
+ def solution
365
+ 3
366
+ end
367
+ end
368
+
369
+
370
+ class Client
371
+ inject Solution()
372
+
373
+ def self.solve
374
+ Solution().tags.each { |e|
375
+ update e
376
+ puts new.solution rescue nil
377
+ }
378
+
379
+ # or...
380
+
381
+ solutions = Solution().tags.each
382
+ begin
383
+ update solutions.next
384
+ puts solved = new().solution()
385
+ end until solved
386
+ solved
387
+ end
388
+
389
+ end
390
+
391
+ $stdout.should_receive(:puts).with(1)
392
+ $stdout.should_receive(:puts).with(2)
393
+ $stdout.should_receive(:puts).with(3)
394
+ $stdout.should_receive(:puts).with(1)
395
+
396
+ Client.solve
397
+
398
+ end
399
+
400
+ end
401
+
402
+ # describe 'use in rails' do
403
+ #
404
+ # it 'allows replacing draper'
405
+ # it 'allows decorating anything not just models'
406
+ #
407
+ # end
408
+
409
+ end
410
+