jackbox 0.9.6.2 → 0.9.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -380,7 +380,7 @@ describe Injectors, :injectors do
380
380
  include Color
381
381
 
382
382
  end
383
- Widget.injectors.sym_list.should == [:layout, :color]
383
+ Widget.injectors.sym_list.should == [:color, :layout]
384
384
 
385
385
  expect{Widget.new.expand}.to_not raise_error
386
386
  expect{Widget.new.tint}.to_not raise_error
@@ -418,7 +418,7 @@ describe Injectors, :injectors do
418
418
  injector :vanilla
419
419
 
420
420
  cup = Coffee.new.enrich(milk).enrich(vanilla)
421
- cup.injectors.sym_list.should == [:milk, :vanilla]
421
+ cup.injectors.sym_list.should == [:vanilla, :milk]
422
422
 
423
423
  end
424
424
 
@@ -428,14 +428,14 @@ describe Injectors, :injectors do
428
428
  inject injector :one
429
429
  inject injector :two
430
430
  end
431
- SomeClass.injectors.sym_list.should == [:one, :two]
431
+ SomeClass.injectors.sym_list.should == [:two, :one]
432
432
 
433
433
  end
434
434
 
435
435
  the 'same is true at the class instance level' do
436
436
 
437
437
  # from above
438
- SomeClassInstance.injectors.sym_list.should == [:class_instance_injector]
438
+ SomeClassInstance.injectors(:all).sym_list.should == [:class_instance_injector]
439
439
 
440
440
  end
441
441
 
@@ -480,7 +480,7 @@ describe Injectors, :injectors do
480
480
  end
481
481
 
482
482
  the 'functionality removed from a class INSTANCE
483
- Note: when applied via the enrich keywork on the class' do
483
+ Note: when applied via the enrich keyword on the class' do
484
484
 
485
485
  injector :part do
486
486
  def connector
@@ -492,7 +492,7 @@ describe Injectors, :injectors do
492
492
  Whole.extend part
493
493
 
494
494
  Whole.connector.should == 'connected'
495
- Whole.injectors.sym_list.should == [:part]
495
+ Whole.injectors(:all).sym_list.should == [:part]
496
496
 
497
497
  # eject the part
498
498
 
@@ -526,7 +526,7 @@ describe Injectors, :injectors do
526
526
  end
527
527
  end
528
528
  end
529
- Home.injectors.sym_list.should == [:layout, :materials ]
529
+ Home.injectors.sym_list.should == [:materials, :layout ]
530
530
 
531
531
  # build
532
532
  my_home = Home.new
@@ -602,7 +602,7 @@ describe Injectors, :injectors do
602
602
  tester1.order(50).should match( /|tester1| label for 50/ ) # call decorated method extended to self
603
603
 
604
604
 
605
- $stdout.should_receive(:puts).with("|tester1| label for 30")
605
+ $stdout.should_receive(:puts).with( /|tester1| label for 30/ )
606
606
  with tester1 do # with self(tester1)
607
607
  puts order 30 # execute method
608
608
  def receive weight # define singleton method
@@ -685,49 +685,49 @@ describe Injectors, :injectors do
685
685
 
686
686
  the 'following class injection forms are all equivalent' do
687
687
 
688
- injector :First do
688
+ injector :Base do
689
689
  def meth
690
690
  :meth
691
691
  end
692
692
  end
693
- Injected.inject First()
693
+ Injected.inject Base()
694
694
  Injected.new.meth.should == :meth
695
695
 
696
- Injected.eject First()
696
+ Injected.eject Base()
697
697
  end
698
698
  the 'following class injection forms are all equivalent' do
699
699
 
700
- Injected.inject First() do
700
+ Injected.inject Base() do
701
701
  def meth
702
702
  :meth
703
703
  end
704
704
  end
705
705
  Injected.new.meth.should == :meth
706
706
 
707
- Injected.eject First()
707
+ Injected.eject Base()
708
708
  end
709
709
  the 'following class injection forms are all equivalent' do
710
710
 
711
- injector( :First ){
711
+ injector( :Base ){
712
712
  def meth
713
713
  :meth
714
714
  end
715
715
  }
716
- Injected.inject First()
716
+ Injected.inject Base()
717
717
  Injected.new.meth.should == :meth
718
718
 
719
- Injected.eject First()
719
+ Injected.eject Base()
720
720
  end
721
721
  the 'following class injection forms are all equivalent' do
722
722
 
723
- Injected.inject injector( :First ){
723
+ Injected.inject injector( :Base ){
724
724
  def meth
725
725
  :meth
726
726
  end
727
727
  }
728
728
  Injected.new.meth.should == :meth
729
729
 
730
- Injected.eject First()
730
+ Injected.eject Base()
731
731
  end
732
732
  end
733
733
 
@@ -735,49 +735,49 @@ describe Injectors, :injectors do
735
735
 
736
736
  the 'following instance enrichment forms are all equvalent' do
737
737
 
738
- injector :second do
738
+ injector :base do
739
739
  def meth
740
740
  :meth
741
741
  end
742
742
  end
743
- enrich second
743
+ enrich base
744
744
  meth.should == :meth
745
745
 
746
- eject second
746
+ eject base
747
747
  end
748
748
  the 'following instance enrichment forms are all equvalent' do
749
749
 
750
- enrich injector :second do
750
+ enrich injector :base do
751
751
  def meth
752
752
  :meth
753
753
  end
754
754
  end
755
755
  meth.should == :meth
756
756
 
757
- eject second
757
+ eject base
758
758
  end
759
759
  the 'following instance enrichment forms are all equvalent' do
760
760
 
761
- injector( :second ){
761
+ injector( :base ){
762
762
  def meth
763
763
  :meth
764
764
  end
765
765
  }
766
- enrich second
766
+ enrich base
767
767
  meth.should == :meth
768
768
 
769
- eject second
769
+ eject base
770
770
  end
771
771
  the 'following instance enrichment forms are all equvalent' do
772
772
 
773
- enrich injector( :second ){
773
+ enrich injector( :base ){
774
774
  def meth
775
775
  :meth
776
776
  end
777
777
  }
778
778
  meth.should == :meth
779
779
 
780
- eject second
780
+ eject base
781
781
  end
782
782
 
783
783
  end
@@ -320,6 +320,7 @@ describe 'Injector versioning:', :injectors do
320
320
  ###################################
321
321
 
322
322
  o.basic(1).should == 2 # basic.1
323
+ # debugger
323
324
  o.compound.should == 11 # compound.1 --local injector binding
324
325
 
325
326
  ###################################
@@ -1,4 +1,5 @@
1
1
  require "spec_helper"
2
+
2
3
  =begin rdoc
3
4
  This file contains the specs for the GOF Decorator Pattern and
4
5
  Strategy Pattern use cases for injectors.
@@ -19,7 +20,8 @@ describe 'some use cases', :injectors do
19
20
  1.50
20
21
  end
21
22
  end
22
-
23
+
24
+ # debugger
23
25
  injector :milk do
24
26
  def cost
25
27
  super() + 0.30
@@ -57,7 +59,7 @@ describe 'some use cases', :injectors do
57
59
  end
58
60
 
59
61
  cup = Coffee.new.enrich(milk).enrich(vanilla).enrich(vanilla)
60
- cup.injectors.sym_list.should == [:milk, :vanilla, :vanilla]
62
+ cup.injectors.sym_list.should == [:vanilla, :vanilla, :milk]
61
63
  cup.cost.should == 2.10
62
64
  cup.should be_instance_of(Coffee)
63
65
 
@@ -94,13 +96,13 @@ describe 'some use cases', :injectors do
94
96
  end
95
97
 
96
98
  cup.enrich(vanilla)
97
- cup.injectors.sym_list.should == [:milk, :vanilla, :vanilla]
99
+ cup.injectors.sym_list.should == [:vanilla, :vanilla, :milk]
98
100
  cup.cost.should == 2.10
99
101
  cup.appearance.should == 'extra red vanilla'
100
102
 
101
103
  end
102
104
 
103
- a 'bigger example' do
105
+ a 'bigger example using normal Injector inheritance' do
104
106
 
105
107
  # some data
106
108
 
@@ -130,7 +132,7 @@ describe 'some use cases', :injectors do
130
132
 
131
133
  DesktopDecorator = WidgetDecorator do
132
134
  def render
133
- dim '600px', '200px'
135
+ dim '600px', '200px' # inherited
134
136
  %{
135
137
  <style>
136
138
  #MyWidget{
@@ -146,7 +148,7 @@ describe 'some use cases', :injectors do
146
148
 
147
149
  MobileDecorator = WidgetDecorator do
148
150
  def render content
149
- dim '200px', '600px'
151
+ dim '200px', '600px' # inherited
150
152
  %{
151
153
  <style>
152
154
  #MyWidget{
@@ -165,6 +167,8 @@ describe 'some use cases', :injectors do
165
167
 
166
168
  browser = 'Safari'
167
169
  @content = database_content
170
+
171
+ # apply the decorators
168
172
 
169
173
  my_widget = case browser
170
174
  when match(/Safari|Firefox|IE/)
@@ -187,8 +191,144 @@ describe 'some use cases', :injectors do
187
191
  }.split.join
188
192
  )
189
193
 
194
+ WidgetDecorator(:implode)
195
+
190
196
  end
191
197
 
198
+ a 'different way of doing it using: JIT inheritance' do
199
+
200
+ # some data
201
+
202
+ def database_content
203
+ %{car truck airplane boat}
204
+ end
205
+
206
+ # rendering helper controls
207
+
208
+ class MyWidgetClass
209
+ def initialize(content)
210
+ @content = content
211
+ end
212
+
213
+ def render
214
+ "<div id='MyWidget'>#{@content}</div>"
215
+ end
216
+ end
217
+
218
+
219
+ MainDecorator = injector :WidgetDecorator do
220
+
221
+ attr_accessor :font, :width, :height
222
+
223
+ def dim(width, heigth)
224
+ @width, @heigth = width, heigth
225
+ end
226
+
227
+ def render
228
+ %{
229
+ <style>
230
+ #MyWidget{
231
+ font: 14px, #{@font};
232
+ width:#{@width};
233
+ height: #{@heigth}
234
+ }
235
+ </style>
236
+ #{super()}
237
+ }
238
+ end
239
+ end
240
+
241
+ # somewhere in a view
242
+
243
+ browser = 'Safari'
244
+ @content = database_content
245
+
246
+ my_widget = case browser
247
+ when match(/Safari|Firefox|IE/)
248
+ # debugger
249
+ MyWidgetClass.new(@content).enrich(WidgetDecorator() do
250
+
251
+ def render # override invoking JIT inheritance
252
+ dim '600px', '200px' # normal inherited method call
253
+ @font = 'helvetica'
254
+
255
+ super()
256
+ end
257
+ end)
258
+
259
+ else
260
+ MyWidgetClass.new(@content).enrich(WidgetDecorator() do
261
+
262
+ def render # override invoking JIT inheritance
263
+ dim '200px', '600px' # normal inherited method call
264
+ @font ='arial'
265
+
266
+ super()
267
+ end
268
+ end)
269
+ end
270
+
271
+ expect(WidgetDecorator().ancestors).to eq([WidgetDecorator(), MainDecorator])
272
+
273
+ expect(
274
+ my_widget.render.split.join).to eq( # split.join used for comparison
275
+ %{
276
+ <style>
277
+ #MyWidget {
278
+ font: 14px, helvetica;
279
+ width:600px;
280
+ height:200px
281
+ }
282
+ </style>
283
+ <div id='MyWidget'>car truck airplane boat</div>
284
+ }.split.join
285
+ )
286
+
287
+
288
+ # browser = 'mobile'
289
+ # @content = database_content
290
+ #
291
+ # my_widget = case browser
292
+ # when match(/Safari|Firefox|IE/)
293
+ # # debugger
294
+ # MyWidgetClass.new(@content).enrich(WidgetDecorator() do
295
+ #
296
+ # def render
297
+ # dim '600px', '200px'
298
+ # @font ='helvetica'
299
+ #
300
+ # super()
301
+ # end
302
+ # end)
303
+ # else
304
+ # MyWidgetClass.new(@content).enrich(WidgetDecorator() do
305
+ # def render
306
+ # dim '200px', '600px'
307
+ # @font ='arial'
308
+ #
309
+ # super()
310
+ # end
311
+ # end)
312
+ # end
313
+ # expect(
314
+ #
315
+ # my_widget.render.split.join).to eq( # split.join used for comparison
316
+ # %{
317
+ # <style>
318
+ # #MyWidget {
319
+ # font: 14px, arial;
320
+ # width:200px;
321
+ # height:600px
322
+ # }
323
+ # </style>
324
+ # <div id='MyWidget'>car truck airplane boat</div>
325
+ # }.split.join
326
+ # )
327
+
328
+ WidgetDecorator(:implode)
329
+
330
+ end
331
+
192
332
  end
193
333
 
194
334
  describe 'strategy pattern.' do
@@ -396,15 +536,7 @@ describe 'some use cases', :injectors do
396
536
  Client.solve
397
537
 
398
538
  end
399
-
400
539
  end
401
540
 
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
541
  end
410
542
 
@@ -1,14 +1,153 @@
1
1
  require "spec_helper"
2
2
  =begin rdoc
3
- This file represents a new approach to refining a class using Jackbox modular closures.
3
+
4
+ This file represents a different approach to refining a class using Jackbox Modular Closures.
4
5
 
5
6
  lha
7
+
6
8
  =end
7
9
 
10
+
8
11
  # Jackbox Reclassings
9
12
  ############################################
10
13
 
11
14
  # RubyProf.start
15
+ describe 're-classings' do
16
+
17
+ it 'refines classes within namespaces' do
18
+
19
+ module Work
20
+ lets String do
21
+ def self.new(*args)
22
+ "+++#{super}+++"
23
+ end
24
+ end
25
+ end
26
+
27
+ class WorkAholic
28
+ include Work
29
+
30
+ def work_method
31
+ String('Men-At-Work')
32
+ end
33
+ end
34
+
35
+ str = WorkAholic.new.work_method
36
+ str.should == '+++Men-At-Work+++'
37
+
38
+ str = String('Men-At-Work') # Regular Kernel version
39
+ str = 'Men-At-Work'
40
+
41
+ end
42
+
43
+ it 'works with Ruby Code Injectors' do
44
+ #
45
+ # Our first Injector
46
+ #
47
+ Sr1 = jack :StringRefinements do
48
+ lets String do
49
+ def self.new *args, &code
50
+ super(*args, &code) + ' is a special string'
51
+ end
52
+ end
53
+ end
54
+
55
+ class OurClass
56
+ include Sr1 # include Tag
57
+
58
+ def foo_bar
59
+ String('foo and bar')
60
+ end
61
+ end
62
+
63
+ c = OurClass.new
64
+
65
+ c.foo_bar.class.should == String
66
+ c.foo_bar.should == 'foo and bar is a special string'
67
+ expect{c.foo_bar.extra.should == :extra}.to raise_error(NoMethodError)
68
+
69
+ #
70
+ # A second injector in the mix
71
+ #
72
+ jack :Log do
73
+ require 'logger'
74
+ def to_log arg
75
+ (@log ||= Logger.new($stdout)).warn(arg)
76
+ end
77
+ end
78
+
79
+ StringRefinements do
80
+ String() do
81
+ inject Log()
82
+
83
+ def show
84
+ to_log self
85
+ end
86
+ end
87
+ end
88
+
89
+ c.foo_bar.class.should == String
90
+ c.foo_bar.should == 'foo and bar is a special string'
91
+
92
+ $stdout.should_receive(:write).with(/foo and bar is a special string/).at_least(1)
93
+
94
+ c.foo_bar.show
95
+
96
+ #
97
+ # lets redfine our first String()
98
+ # -- SR1 and SR2 are different injectable String()
99
+ #
100
+ Sr2 = StringRefinements do # New String refinement
101
+ lets String do
102
+ inject Log()
103
+
104
+ def self.new *args
105
+ super + '****'
106
+ end
107
+ end
108
+ end
109
+
110
+ class OurOtherClass
111
+ include Sr2 # Apply new tag
112
+
113
+ def foo_bar
114
+ String('foo and bar')
115
+ end
116
+ end
117
+
118
+ d = OurOtherClass.new
119
+
120
+ d.foo_bar.class.should == String
121
+ d.foo_bar.should == 'foo and bar****'
122
+
123
+ expect{ d.foo_bar.show }.to raise_error(NoMethodError)
124
+ $stdout.should_receive(:write).with(/foo/).at_least(1)
125
+ expect{ d.foo_bar.to_log 'foo' }.to_not raise_error
126
+
127
+ # c is still the same
128
+
129
+ c.foo_bar.class.should == String
130
+ c.foo_bar.should == 'foo and bar is a special string'
131
+
132
+
133
+ # String is untouched
134
+
135
+ String("foo").should == 'foo'
136
+ String.new("foo").should == 'foo'
137
+
138
+ end
139
+ end
140
+
141
+
142
+ # ################################# IMPORTANT ########################################
143
+ # #
144
+ # Although the above is for what reclassings are designed, in the following exmaples #
145
+ # we test some of the more basic and ruby integration aspects of re-classings. #
146
+ # Note: reclassings used on a top level will hide any Kernel methods by the same #
147
+ # type name. Their use case is like the above or in some name space. See below. #
148
+ # #
149
+ # ################################# IMPORTANT ########################################
150
+
12
151
 
13
152
  injector :StringExtensions do # define injector
14
153
  def to_s
@@ -16,8 +155,9 @@ injector :StringExtensions do # define injector
16
155
  end
17
156
  end
18
157
 
19
- # debugger
20
- lets String do # apply to class
158
+ # Note: This reclassing hides Kernel.String() -- use
159
+ # fully qualified name to access original version
160
+ lets String do # apply injector
21
161
  include StringExtensions()
22
162
  end
23
163
 
@@ -35,7 +175,8 @@ describe :String do
35
175
  end
36
176
 
37
177
 
38
- # Another Reclassing
178
+ # Another Top-level Reclassing
179
+ # Note: same as above
39
180
 
40
181
  jack :ArrayExtensions do
41
182
  def to_s
@@ -122,6 +263,7 @@ module M7
122
263
  def foo_bar
123
264
  Array(2)
124
265
  end
266
+
125
267
  end
126
268
 
127
269
  class A6
@@ -142,9 +284,9 @@ end
142
284
 
143
285
 
144
286
 
145
- # Further Introspection
287
+ # Introspection
146
288
  ##################################################
147
- # debugger
289
+
148
290
  assert( A6.new.foo_bar.injectors.by_name == [:NameSpacedArrayExtensions] )
149
291
 
150
292
  describe "introspection" do
@@ -152,11 +294,23 @@ describe "introspection" do
152
294
  # introspecting on capabilities
153
295
 
154
296
  it 'should allow injector introspection' do
155
- # # top level re-class
297
+
298
+ StringRefinements do
299
+ (reclass? String).should == true
300
+
301
+ String() do
302
+ injectors.by_name.should == [:Log]
303
+ end
304
+ end
305
+
306
+ end
307
+
308
+ it 'should allow injector introspection' do
309
+ # top level re-class
156
310
  Array() do
157
311
  injectors.by_name.should == [:ArrayExtensions]
158
312
  end
159
- # debugger
313
+
160
314
  Array(){injectors.by_name}.should == [:ArrayExtensions]
161
315
 
162
316
  # top level re-class instances
@@ -165,11 +319,13 @@ describe "introspection" do
165
319
  end
166
320
 
167
321
  it 'works on namespaced reclassings' do
322
+
168
323
  module M7
169
- # debugger
324
+
170
325
  Array() do
171
326
  injectors.by_name.should == [:NameSpacedArrayExtensions]
172
327
  end
328
+
173
329
  end
174
330
  end
175
331
 
@@ -192,75 +348,6 @@ describe "introspection" do
192
348
 
193
349
  end
194
350
 
195
- it 'works' do
196
-
197
- # Injector declaration
198
-
199
- jack :StringRefinements do
200
- lets String do
201
- with singleton_class do
202
- alias _new new
203
- def new *args, &code
204
- super(*args, &code) + ' is a special string'
205
- end
206
- end
207
- end
208
- end
209
-
210
- class OurClass
211
- include StringRefinements()
212
-
213
- def foo_bar
214
- String('foo and bar')
215
- end
216
- end
217
-
218
- c = OurClass.new
219
- c.foo_bar.class.should == String
220
- c.foo_bar.should == 'foo and bar is a special string'
221
- expect{c.foo_bar.extra.should == :extra}.to raise_error(NoMethodError)
222
-
223
- StringRefinements do
224
- String() do
225
- def extra
226
- :extra
227
- end
228
- end
229
- end
230
-
231
- c.foo_bar.should == 'foo and bar is a special string'
232
- c.foo_bar.class.should == String
233
- c.foo_bar.extra.should == :extra
234
-
235
- SR = StringRefinements do # New Version
236
- lets String do
237
- def to_s
238
- super + '****'
239
- end
240
- end
241
- end
242
-
243
- # c is still the same
244
-
245
- c.foo_bar.should == 'foo and bar is a special string'
246
- c.foo_bar.class.should == String
247
- c.foo_bar.extra.should == :extra
248
-
249
-
250
- class OurOtherClass
251
- include SR # Apply new version
252
- # to another class
253
- def foo_bar
254
- String('foo and bar')
255
- end
256
- end
257
-
258
- d = OurOtherClass.new
259
- d.foo_bar.should == 'foo and bar'
260
- d.foo_bar.to_s.should == 'foo and bar****'
261
- expect{ d.extra }.to raise_error(NoMethodError)
262
-
263
- end
264
351
  end
265
352
 
266
353