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.
- checksums.yaml +13 -5
- data/CHANGES.txt +41 -1
- data/LICENSE.lic +0 -0
- data/README.md +244 -149
- data/Rakefile +6 -6
- data/jackbox.gemspec +3 -2
- data/lib/jackbox.rb +1 -1
- data/lib/jackbox/injectors.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/lib/abtract_spec.rb +6 -6
- data/spec/lib/jackbox/injector_composition_spec.rb +106 -88
- data/spec/lib/jackbox/injector_directives_spec.rb +46 -0
- data/spec/lib/jackbox/injector_inheritance_spec.rb +980 -410
- data/spec/lib/jackbox/injector_introspection_spec.rb +333 -208
- data/spec/lib/jackbox/injector_spec.rb +28 -28
- data/spec/lib/jackbox/injector_versioning_spec.rb +1 -0
- data/spec/lib/jackbox/patterns_spec.rb +146 -14
- data/spec/lib/jackbox/reclassing_spec.rb +165 -78
- data/spec/lib/jackbox/vmc_spec.rb +246 -0
- metadata +32 -28
| @@ -380,7 +380,7 @@ describe Injectors, :injectors do | |
| 380 380 | 
             
            				include Color
         | 
| 381 381 |  | 
| 382 382 | 
             
            			end
         | 
| 383 | 
            -
            			Widget.injectors.sym_list.should == [: | 
| 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 == [: | 
| 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 == [: | 
| 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  | 
| 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 == [: | 
| 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( | 
| 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 : | 
| 688 | 
            +
            					injector :Base do
         | 
| 689 689 | 
             
            						def meth
         | 
| 690 690 | 
             
            							:meth
         | 
| 691 691 | 
             
            						end
         | 
| 692 692 | 
             
            					end
         | 
| 693 | 
            -
            					Injected.inject  | 
| 693 | 
            +
            					Injected.inject Base()
         | 
| 694 694 | 
             
            					Injected.new.meth.should == :meth  
         | 
| 695 695 |  | 
| 696 | 
            -
            					Injected.eject  | 
| 696 | 
            +
            					Injected.eject Base()
         | 
| 697 697 | 
             
            				end
         | 
| 698 698 | 
             
            				the 'following class injection forms are all equivalent' do
         | 
| 699 699 |  | 
| 700 | 
            -
            					Injected.inject  | 
| 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  | 
| 707 | 
            +
            					Injected.eject Base()
         | 
| 708 708 | 
             
            				end 
         | 
| 709 709 | 
             
            				the 'following class injection forms are all equivalent' do
         | 
| 710 710 |  | 
| 711 | 
            -
            					injector( : | 
| 711 | 
            +
            					injector( :Base ){
         | 
| 712 712 | 
             
            						def meth
         | 
| 713 713 | 
             
            							:meth
         | 
| 714 714 | 
             
            						end
         | 
| 715 715 | 
             
            					}
         | 
| 716 | 
            -
            					Injected.inject  | 
| 716 | 
            +
            					Injected.inject Base()
         | 
| 717 717 | 
             
            					Injected.new.meth.should == :meth
         | 
| 718 718 |  | 
| 719 | 
            -
            					Injected.eject  | 
| 719 | 
            +
            					Injected.eject Base()
         | 
| 720 720 | 
             
            				end
         | 
| 721 721 | 
             
            				the 'following class injection forms are all equivalent' do
         | 
| 722 722 |  | 
| 723 | 
            -
            					Injected.inject injector( : | 
| 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  | 
| 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 : | 
| 738 | 
            +
            					injector :base do
         | 
| 739 739 | 
             
            						def meth
         | 
| 740 740 | 
             
            							:meth
         | 
| 741 741 | 
             
            						end
         | 
| 742 742 | 
             
            					end
         | 
| 743 | 
            -
            					enrich  | 
| 743 | 
            +
            					enrich base
         | 
| 744 744 | 
             
            					meth.should == :meth
         | 
| 745 745 |  | 
| 746 | 
            -
            					eject  | 
| 746 | 
            +
            					eject base
         | 
| 747 747 | 
             
            				end
         | 
| 748 748 | 
             
            				the 'following instance enrichment forms are all equvalent' do
         | 
| 749 749 |  | 
| 750 | 
            -
            					enrich injector : | 
| 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  | 
| 757 | 
            +
            					eject base
         | 
| 758 758 | 
             
            				end
         | 
| 759 759 | 
             
            				the 'following instance enrichment forms are all equvalent' do
         | 
| 760 760 |  | 
| 761 | 
            -
            					injector( : | 
| 761 | 
            +
            					injector( :base ){
         | 
| 762 762 | 
             
            						def meth
         | 
| 763 763 | 
             
            							:meth
         | 
| 764 764 | 
             
            						end
         | 
| 765 765 | 
             
            					}
         | 
| 766 | 
            -
            					enrich  | 
| 766 | 
            +
            					enrich base
         | 
| 767 767 | 
             
            					meth.should == :meth
         | 
| 768 768 |  | 
| 769 | 
            -
            					eject  | 
| 769 | 
            +
            					eject base
         | 
| 770 770 | 
             
            				end
         | 
| 771 771 | 
             
            				the 'following instance enrichment forms are all equvalent' do
         | 
| 772 772 |  | 
| 773 | 
            -
            					enrich injector( : | 
| 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  | 
| 780 | 
            +
            					eject base
         | 
| 781 781 | 
             
            				end 
         | 
| 782 782 |  | 
| 783 783 | 
             
            			end
         | 
| @@ -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 == [: | 
| 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 == [: | 
| 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 | 
            -
             | 
| 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 | 
            -
            #  | 
| 20 | 
            -
             | 
| 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 | 
            -
            #  | 
| 287 | 
            +
            # Introspection
         | 
| 146 288 | 
             
            ##################################################
         | 
| 147 | 
            -
             | 
| 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 | 
            -
            		 | 
| 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 | 
            -
             | 
| 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 | 
            -
             | 
| 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 |  |