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
| @@ -264,3 +264,49 @@ to re-inject them into every object they modify' do | |
| 264 264 | 
             
            	end
         | 
| 265 265 |  | 
| 266 266 | 
             
            end
         | 
| 267 | 
            +
             | 
| 268 | 
            +
            describe 'more interesting uses' do
         | 
| 269 | 
            +
            	
         | 
| 270 | 
            +
            	it 'allows the following' do
         | 
| 271 | 
            +
            		
         | 
| 272 | 
            +
            		facet :PreFunction do
         | 
| 273 | 
            +
            			def pre_function
         | 
| 274 | 
            +
            				puts '++++++++++'
         | 
| 275 | 
            +
            			end
         | 
| 276 | 
            +
            		end
         | 
| 277 | 
            +
            		
         | 
| 278 | 
            +
            		facet :PosFunction do
         | 
| 279 | 
            +
            			def pos_function
         | 
| 280 | 
            +
            				puts '=========='
         | 
| 281 | 
            +
            			end
         | 
| 282 | 
            +
            		end
         | 
| 283 | 
            +
            		
         | 
| 284 | 
            +
            		class Model
         | 
| 285 | 
            +
            			
         | 
| 286 | 
            +
            			inject PreFunction(:silence)
         | 
| 287 | 
            +
            			inject PosFunction(:silence) 
         | 
| 288 | 
            +
            			
         | 
| 289 | 
            +
            			def meth arg
         | 
| 290 | 
            +
            				pre_function
         | 
| 291 | 
            +
            				puts arg * arg
         | 
| 292 | 
            +
            				pos_function
         | 
| 293 | 
            +
            			end
         | 
| 294 | 
            +
            		end
         | 
| 295 | 
            +
            		
         | 
| 296 | 
            +
            		obj = Model.new
         | 
| 297 | 
            +
            		
         | 
| 298 | 
            +
            		$stdout.should_receive(:puts).with(4)
         | 
| 299 | 
            +
            		obj.meth( 2 )
         | 
| 300 | 
            +
            		
         | 
| 301 | 
            +
            		PreFunction(:active)
         | 
| 302 | 
            +
            		PosFunction(:active)
         | 
| 303 | 
            +
             | 
| 304 | 
            +
            		$stdout.should_receive(:puts).with('++++++++++')
         | 
| 305 | 
            +
            		$stdout.should_receive(:puts).with(4)
         | 
| 306 | 
            +
            		$stdout.should_receive(:puts).with('==========')
         | 
| 307 | 
            +
            		obj.meth( 2 )
         | 
| 308 | 
            +
             | 
| 309 | 
            +
            	end
         | 
| 310 | 
            +
            	
         | 
| 311 | 
            +
            	
         | 
| 312 | 
            +
            end
         | 
| @@ -13,60 +13,89 @@ require "spec_helper" | |
| 13 13 |  | 
| 14 14 | 
             
            include Injectors
         | 
| 15 15 |  | 
| 16 | 
            +
            	
         | 
| 17 | 
            +
            	####################### IMPORTANT ##############################
         | 
| 18 | 
            +
            	# NOTE: Once again, some of these examples are long on purpose.
         | 
| 19 | 
            +
            	# We are trying to show what happens to Injectors as 
         | 
| 20 | 
            +
            	# a result of various lifecycle change events.
         | 
| 21 | 
            +
            	# ##############################################################
         | 
| 22 | 
            +
             | 
| 23 | 
            +
             | 
| 24 | 
            +
             | 
| 25 | 
            +
            # RubyProf.start
         | 
| 16 26 | 
             
            describe "ancestor chains" do
         | 
| 17 27 |  | 
| 18 28 | 
             
            	it 'updates the ancestor chains accordingly based on: injections and ejections' do
         | 
| 19 | 
            -
             | 
| 29 | 
            +
             | 
| 30 | 
            +
                # LifeCycle Start
         | 
| 31 | 
            +
             | 
| 20 32 | 
             
            		injector :Parent															# capitalized method
         | 
| 33 | 
            +
            		
         | 
| 21 34 | 
             
            		class Child
         | 
| 22 35 | 
             
            			include Parent()
         | 
| 23 36 | 
             
            		end
         | 
| 24 | 
            -
            		 | 
| 37 | 
            +
            		c = Child.new
         | 
| 38 | 
            +
            		
         | 
| 39 | 
            +
            		# Parent is ancestor of the class and instance
         | 
| 40 | 
            +
            		Child.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )
         | 
| 41 | 
            +
            		c.singleton_class.ancestors.to_s.should match(/Child, \(\|Parent\|.*\), Object.*BasicObject/ )
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            		# Parent is ancestor of the class and of the instance metaclass
         | 
| 44 | 
            +
            		c.enrich Parent()                                                      
         | 
| 45 | 
            +
            		c.singleton_class.ancestors.to_s.should match( /\(\|Parent\|.*\), Child, \(\|Parent\|.*\), Object.*BasicObject/ )
         | 
| 25 46 |  | 
| 26 | 
            -
            		c = Child.new.enrich Parent()                                                      
         | 
| 27 | 
            -
            		# Parent is ancestor of the class and of the metaclass
         | 
| 28 | 
            -
            		c.singleton_class.ancestors.to_s.should match( /\(.*\|Parent\|\), Child, \(.*\|Parent\|\), Object.*BasicObject/ )
         | 
| 29 47 |  | 
| 30 | 
            -
            		c.eject Parent()
         | 
| 31 48 | 
             
            		# Parent is ejected from the object metaclass and ancestor chain reverts back
         | 
| 32 | 
            -
            		c. | 
| 49 | 
            +
            		c.eject Parent()
         | 
| 50 | 
            +
            		c.singleton_class.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )
         | 
| 51 | 
            +
             | 
| 33 52 |  | 
| 34 | 
            -
            		Child.eject Parent()
         | 
| 35 53 | 
             
            		# Parent is ejected from the class and ancestors chain is empty
         | 
| 54 | 
            +
            		Child.eject Parent()
         | 
| 36 55 | 
             
            		Child.ancestors.to_s.should match( /Child, Object.*BasicObject/ )
         | 
| 37 | 
            -
             | 
| 56 | 
            +
             | 
| 57 | 
            +
             | 
| 58 | 
            +
            		# Note: cannot update empty injector
         | 
| 38 59 | 
             
            		expect{ Child.send :update, Child.parent }.to raise_error(NoMethodError) 
         | 
| 39 60 |  | 
| 61 | 
            +
             | 
| 62 | 
            +
            		# Instance metaclass is extended with Parent twice like in the case of multiple decorators
         | 
| 40 63 | 
             
            		c.enrich Parent()
         | 
| 41 64 | 
             
            		c.enrich Parent()
         | 
| 42 | 
            -
            		 | 
| 43 | 
            -
             | 
| 65 | 
            +
            		c.singleton_class.ancestors.to_s.should match( /\(\|Parent\|.*\), \(\|Parent\|.*\), Child, Object.*BasicObject/ )
         | 
| 66 | 
            +
             | 
| 44 67 |  | 
| 68 | 
            +
            		# Instance is reverted back to no Injectors
         | 
| 45 69 | 
             
            		c.eject Parent()
         | 
| 46 70 | 
             
            		c.eject Parent()
         | 
| 47 | 
            -
            		# object is reverted back to no Injectors
         | 
| 48 71 | 
             
            		c.singleton_class.ancestors.to_s.should match( /Child, Object.*BasicObject/ )
         | 
| 49 72 |  | 
| 73 | 
            +
             | 
| 74 | 
            +
            		# LyfeCycle Restart
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            		# class is re-injected with Parent and becomes ancestor of the class and instance
         | 
| 50 77 | 
             
            		Child.inject Parent()
         | 
| 51 | 
            -
            		 | 
| 52 | 
            -
            		Child.ancestors.to_s.should match( /Child, \( | 
| 53 | 
            -
            		c.singleton_class.ancestors.to_s.should match( /Child, \( | 
| 78 | 
            +
            		
         | 
| 79 | 
            +
            		Child.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )              
         | 
| 80 | 
            +
            		c.singleton_class.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )
         | 
| 54 81 |  | 
| 82 | 
            +
             | 
| 83 | 
            +
            		# Parent is eject from the instance
         | 
| 55 84 | 
             
            		c.eject Parent()
         | 
| 56 | 
            -
            		# class level Injector ejected from single object and ancestor for the object updated but not for class
         | 
| 57 85 | 
             
            		c.singleton_class.ancestors.to_s.should match( /Child, Object.*BasicObject/ )
         | 
| 58 | 
            -
            		Child.ancestors.to_s.should match( /Child, \( | 
| 86 | 
            +
            		Child.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )
         | 
| 87 | 
            +
             | 
| 59 88 |  | 
| 89 | 
            +
            		# Class-level Injector update re-introduces it to objects that have ejected it locally and ancestors is updated
         | 
| 60 90 | 
             
            		Child.send :update, Parent()
         | 
| 61 | 
            -
            		 | 
| 62 | 
            -
            		c.singleton_class.ancestors.to_s.should match( /Child, \(.*\|Parent\|\), Object.*BasicObject/ )
         | 
| 91 | 
            +
            		c.singleton_class.ancestors.to_s.should match( /Child, \(\|Parent\|.*\), Object.*BasicObject/ )
         | 
| 63 92 |  | 
| 64 93 | 
             
            	end
         | 
| 65 94 | 
             
            end
         | 
| 66 95 |  | 
| 67 | 
            -
            describe "the  | 
| 96 | 
            +
            describe "the behavior of injectors under class inheritance" do
         | 
| 68 97 |  | 
| 69 | 
            -
            	example " | 
| 98 | 
            +
            	example "working accross class hierarchies and the effects of ejection" do
         | 
| 70 99 |  | 
| 71 100 |  | 
| 72 101 | 
             
            		###########################################
         | 
| @@ -77,7 +106,7 @@ describe "the inheritance behavior of injectors" do | |
| 77 106 | 
             
                class C
         | 
| 78 107 | 
             
                end
         | 
| 79 108 | 
             
                C.inject j { 																	# #foo pre-defined at time of injection
         | 
| 80 | 
            -
                  def  | 
| 109 | 
            +
                  def m1
         | 
| 81 110 | 
             
                    'foo'
         | 
| 82 111 | 
             
                  end
         | 
| 83 112 | 
             
                }
         | 
| @@ -87,167 +116,177 @@ describe "the inheritance behavior of injectors" do | |
| 87 116 | 
             
                injector :k
         | 
| 88 117 |  | 
| 89 118 | 
             
                C.inject k { 																	# #faa pre-defined at injection
         | 
| 90 | 
            -
                  def  | 
| 119 | 
            +
                  def m2
         | 
| 91 120 | 
             
                    'faa'
         | 
| 92 121 | 
             
                  end
         | 
| 93 122 | 
             
                }
         | 
| 94 | 
            -
                C.injectors.sym_list.should == [: | 
| 95 | 
            -
                C.new.injectors.sym_list.should == [: | 
| 123 | 
            +
                C.injectors.sym_list.should == [:k, :j]
         | 
| 124 | 
            +
                C.new.injectors.sym_list.should == [:k, :j]
         | 
| 96 125 |  | 
| 97 | 
            -
                C.new. | 
| 98 | 
            -
                C.new. | 
| 126 | 
            +
                C.new.m1.should == 'foo'
         | 
| 127 | 
            +
                C.new.m2.should == 'faa'
         | 
| 99 128 | 
             
                c = C.new
         | 
| 100 129 |  | 
| 101 130 |  | 
| 131 | 
            +
            		########################################
         | 
| 102 132 | 
             
                # D inherits from C
         | 
| 103 | 
            -
             | 
| 133 | 
            +
            		########################################
         | 
| 104 134 | 
             
                class D < C																		# methods are inherited from j and k
         | 
| 105 135 | 
             
                end
         | 
| 106 | 
            -
                C.injectors.sym_list.should == [: | 
| 107 | 
            -
                C.new.injectors.sym_list.should == [: | 
| 136 | 
            +
                C.injectors.sym_list.should == [:k, :j]
         | 
| 137 | 
            +
                C.new.injectors.sym_list.should == [:k, :j]
         | 
| 108 138 | 
             
                D.injectors.sym_list.should == []
         | 
| 109 139 | 
             
                D.new.injectors.sym_list.should == []
         | 
| 110 140 |  | 
| 111 141 | 
             
            		# New Objects
         | 
| 112 | 
            -
                C.new. | 
| 113 | 
            -
                C.new. | 
| 114 | 
            -
                D.new. | 
| 115 | 
            -
                D.new. | 
| 142 | 
            +
                C.new.m1.should == 'foo'											
         | 
| 143 | 
            +
                C.new.m2.should == 'faa'
         | 
| 144 | 
            +
                D.new.m1.should == 'foo'
         | 
| 145 | 
            +
                D.new.m2.should == 'faa'
         | 
| 116 146 | 
             
            		# Existing Objects
         | 
| 117 147 | 
             
                d = D.new
         | 
| 118 | 
            -
                c. | 
| 119 | 
            -
                c. | 
| 148 | 
            +
                c.m1.should == 'foo'
         | 
| 149 | 
            +
                c.m2.should == 'faa'
         | 
| 120 150 |  | 
| 121 151 |  | 
| 152 | 
            +
            		########################################
         | 
| 122 153 | 
             
            		# inject D and override C
         | 
| 123 | 
            -
            		
         | 
| 154 | 
            +
            		########################################
         | 
| 124 155 | 
             
            		D.inject j { 																	# new version of j pre-defined at injection
         | 
| 125 | 
            -
            			def  | 
| 156 | 
            +
            			def m1
         | 
| 126 157 | 
             
            				'foooo'
         | 
| 127 158 | 
             
            			end
         | 
| 128 159 | 
             
            		}
         | 
| 129 | 
            -
                C.injectors.sym_list.should == [: | 
| 130 | 
            -
                C.new.injectors.sym_list.should == [: | 
| 160 | 
            +
                C.injectors.sym_list.should == [:k, :j]
         | 
| 161 | 
            +
                C.new.injectors.sym_list.should == [:k, :j]
         | 
| 131 162 | 
             
                D.injectors.sym_list.should == [:j]
         | 
| 132 163 | 
             
                D.new.injectors.sym_list.should == [:j]
         | 
| 133 164 |  | 
| 134 165 | 
             
            		# New Objects
         | 
| 135 | 
            -
                D.new. | 
| 166 | 
            +
                D.new.m1.should == 'foooo'										# new version of #foo
         | 
| 136 167 | 
             
            		# still the same
         | 
| 137 | 
            -
                D.new. | 
| 138 | 
            -
                C.new. | 
| 139 | 
            -
                C.new. | 
| 168 | 
            +
                D.new.m2.should == 'faa'
         | 
| 169 | 
            +
                C.new.m1.should == 'foo'
         | 
| 170 | 
            +
                C.new.m2.should == 'faa'
         | 
| 140 171 | 
             
            		# Existing Objects
         | 
| 141 | 
            -
                c. | 
| 142 | 
            -
                c. | 
| 143 | 
            -
                d. | 
| 144 | 
            -
                d. | 
| 172 | 
            +
                c.m1.should == 'foo'
         | 
| 173 | 
            +
                c.m2.should == 'faa'
         | 
| 174 | 
            +
                d.m1.should == 'foooo'
         | 
| 175 | 
            +
                d.m2.should == 'faa'
         | 
| 145 176 |  | 
| 146 177 |  | 
| 178 | 
            +
            		########################################
         | 
| 147 179 | 
             
            		# D class overrides j
         | 
| 148 | 
            -
            		
         | 
| 180 | 
            +
            		########################################
         | 
| 149 181 | 
             
                class D < C
         | 
| 150 | 
            -
                  def  | 
| 182 | 
            +
                  def m1                                     # overrides foo from j
         | 
| 151 183 | 
             
                    'fuu'
         | 
| 152 184 | 
             
                  end
         | 
| 153 185 | 
             
                end
         | 
| 154 | 
            -
                C.injectors.sym_list.should == [: | 
| 155 | 
            -
                C.new.injectors.sym_list.should == [: | 
| 186 | 
            +
                C.injectors.sym_list.should == [:k, :j]
         | 
| 187 | 
            +
                C.new.injectors.sym_list.should == [:k, :j]
         | 
| 156 188 | 
             
                D.injectors.sym_list.should == [:j]
         | 
| 157 189 | 
             
                D.new.injectors.sym_list.should == [:j]
         | 
| 158 190 |  | 
| 159 191 | 
             
            		# New Objects
         | 
| 160 | 
            -
                D.new. | 
| 192 | 
            +
                D.new.m1.should == 'fuu'											# overrided last version from j
         | 
| 161 193 | 
             
            		# still the same
         | 
| 162 | 
            -
                D.new. | 
| 163 | 
            -
                C.new. | 
| 164 | 
            -
                C.new. | 
| 194 | 
            +
                D.new.m2.should == 'faa'
         | 
| 195 | 
            +
                C.new.m1.should == 'foo'
         | 
| 196 | 
            +
                C.new.m2.should == 'faa'
         | 
| 165 197 | 
             
            		# Existing Objects
         | 
| 166 | 
            -
                c. | 
| 167 | 
            -
                c. | 
| 168 | 
            -
                d. | 
| 169 | 
            -
                d. | 
| 198 | 
            +
                c.m1.should == 'foo'
         | 
| 199 | 
            +
                c.m2.should == 'faa'
         | 
| 200 | 
            +
                d.m1.should == 'fuu'													# overrided
         | 
| 201 | 
            +
                d.m2.should == 'faa'
         | 
| 170 202 |  | 
| 171 203 |  | 
| 204 | 
            +
            		########################################
         | 
| 172 205 | 
             
            		# update C and inherit into D
         | 
| 173 | 
            -
            		
         | 
| 206 | 
            +
            		########################################
         | 
| 174 207 | 
             
            		C.send :update, k { 													# new version of k pre-defined at update
         | 
| 175 | 
            -
            			def  | 
| 208 | 
            +
            			def m2																			# -- no other version of k in hierarchy
         | 
| 176 209 | 
             
            				'faaxx'
         | 
| 177 210 | 
             
            			end
         | 
| 178 211 | 
             
            		}
         | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 212 | 
            +
            		# can also be written
         | 
| 213 | 
            +
            		# class C
         | 
| 214 | 
            +
            		# 	update k 				# providing k is in scope
         | 
| 215 | 
            +
            		# end
         | 
| 216 | 
            +
                C.injectors.sym_list.should == [:k, :j]
         | 
| 217 | 
            +
                C.new.injectors.sym_list.should == [:k, :j]
         | 
| 181 218 | 
             
                D.injectors.sym_list.should == [:j]
         | 
| 182 219 | 
             
                D.new.injectors.sym_list.should == [:j]
         | 
| 183 220 |  | 
| 184 221 | 
             
            		# New Objects
         | 
| 185 | 
            -
                C.new. | 
| 186 | 
            -
                D.new. | 
| 222 | 
            +
                C.new.m2.should == 'faaxx'										# new version of #faa
         | 
| 223 | 
            +
                D.new.m2.should == 'faaxx'
         | 
| 187 224 | 
             
            		# still the same
         | 
| 188 | 
            -
                C.new. | 
| 189 | 
            -
                D.new. | 
| 225 | 
            +
                C.new.m1.should == 'foo'
         | 
| 226 | 
            +
                D.new.m1.should == 'fuu'
         | 
| 190 227 | 
             
            		# Existing Objects
         | 
| 191 | 
            -
                c. | 
| 192 | 
            -
                c. | 
| 193 | 
            -
                d. | 
| 194 | 
            -
                d. | 
| 228 | 
            +
                c.m1.should == 'foo'
         | 
| 229 | 
            +
                c.m2.should == 'faaxx'
         | 
| 230 | 
            +
                d.m1.should == 'fuu'
         | 
| 231 | 
            +
                d.m2.should == 'faaxx'
         | 
| 195 232 |  | 
| 196 233 |  | 
| 234 | 
            +
            		########################################
         | 
| 197 235 | 
             
                # E inherits from D
         | 
| 198 | 
            -
             | 
| 236 | 
            +
            		########################################
         | 
| 199 237 | 
             
                class E < D																		# methods are inherited from j at C, D and k update at C
         | 
| 200 238 | 
             
                end
         | 
| 201 | 
            -
                C.injectors.sym_list.should == [: | 
| 202 | 
            -
                C.new.injectors.sym_list.should == [: | 
| 239 | 
            +
                C.injectors.sym_list.should == [:k, :j]
         | 
| 240 | 
            +
                C.new.injectors.sym_list.should == [:k, :j]
         | 
| 203 241 | 
             
                D.injectors.sym_list.should == [:j]
         | 
| 204 242 | 
             
                D.new.injectors.sym_list.should == [:j]
         | 
| 205 243 | 
             
                E.injectors.sym_list.should == []
         | 
| 206 244 | 
             
                E.new.injectors.sym_list.should == []
         | 
| 207 245 |  | 
| 208 246 | 
             
            		# New Objects
         | 
| 209 | 
            -
                C.new. | 
| 210 | 
            -
                C.new. | 
| 211 | 
            -
                D.new. | 
| 212 | 
            -
                D.new. | 
| 213 | 
            -
                E.new. | 
| 214 | 
            -
                E.new. | 
| 247 | 
            +
                C.new.m1.should == 'foo'
         | 
| 248 | 
            +
                C.new.m2.should == 'faaxx'
         | 
| 249 | 
            +
                D.new.m1.should == 'fuu'
         | 
| 250 | 
            +
                D.new.m2.should == 'faaxx'                   # new objects pass
         | 
| 251 | 
            +
                E.new.m1.should == 'fuu'
         | 
| 252 | 
            +
                E.new.m2.should == 'faaxx'
         | 
| 215 253 | 
             
            		# Existing Objects
         | 
| 216 254 | 
             
                e = E.new
         | 
| 217 | 
            -
                c. | 
| 218 | 
            -
                c. | 
| 219 | 
            -
                d. | 
| 220 | 
            -
                d. | 
| 255 | 
            +
                c.m1.should == 'foo'
         | 
| 256 | 
            +
                c.m2.should == 'faaxx'                       # existing objects pass
         | 
| 257 | 
            +
                d.m1.should == 'fuu'
         | 
| 258 | 
            +
                d.m2.should == 'faaxx'
         | 
| 221 259 |  | 
| 222 260 |  | 
| 261 | 
            +
            		########################################
         | 
| 223 262 | 
             
            		# E overrides D
         | 
| 224 | 
            -
            		
         | 
| 263 | 
            +
            		########################################
         | 
| 225 264 | 
             
                class E < D
         | 
| 226 | 
            -
                  def  | 
| 265 | 
            +
                  def m1																			# overrides #foo from j at C, D
         | 
| 227 266 | 
             
                    'fuuuu'
         | 
| 228 267 | 
             
                  end
         | 
| 229 268 | 
             
                end
         | 
| 230 | 
            -
                C.injectors.sym_list.should == [: | 
| 231 | 
            -
                C.new.injectors.sym_list.should == [: | 
| 269 | 
            +
                C.injectors.sym_list.should == [:k, :j]
         | 
| 270 | 
            +
                C.new.injectors.sym_list.should == [:k, :j]
         | 
| 232 271 | 
             
                D.injectors.sym_list.should == [:j]
         | 
| 233 272 | 
             
                D.new.injectors.sym_list.should == [:j]
         | 
| 234 273 | 
             
                E.injectors.sym_list.should == []
         | 
| 235 274 | 
             
                E.new.injectors.sym_list.should == []
         | 
| 236 275 |  | 
| 237 276 | 
             
            		# New Objects
         | 
| 238 | 
            -
                C.new. | 
| 239 | 
            -
                C.new. | 
| 240 | 
            -
                D.new. | 
| 241 | 
            -
                D.new. | 
| 242 | 
            -
                E.new. | 
| 243 | 
            -
                E.new. | 
| 277 | 
            +
                C.new.m1.should == 'foo'
         | 
| 278 | 
            +
                C.new.m2.should == 'faaxx'
         | 
| 279 | 
            +
                D.new.m1.should == 'fuu'
         | 
| 280 | 
            +
                D.new.m2.should == 'faaxx'
         | 
| 281 | 
            +
                E.new.m1.should == 'fuuuu'
         | 
| 282 | 
            +
                E.new.m2.should == 'faaxx'
         | 
| 244 283 | 
             
            		# Existing Objects
         | 
| 245 | 
            -
                c. | 
| 246 | 
            -
                c. | 
| 247 | 
            -
                d. | 
| 248 | 
            -
                d. | 
| 249 | 
            -
                e. | 
| 250 | 
            -
                e. | 
| 284 | 
            +
                c.m1.should == 'foo'
         | 
| 285 | 
            +
                c.m2.should == 'faaxx'
         | 
| 286 | 
            +
                d.m1.should == 'fuu'
         | 
| 287 | 
            +
                d.m2.should == 'faaxx'
         | 
| 288 | 
            +
                e.m1.should == 'fuuuu'
         | 
| 289 | 
            +
                e.m2.should == 'faaxx'
         | 
| 251 290 |  | 
| 252 291 |  | 
| 253 292 | 
             
                #######################################
         | 
| @@ -263,21 +302,24 @@ describe "the inheritance behavior of injectors" do | |
| 263 302 | 
             
                E.injectors.sym_list.should == []
         | 
| 264 303 |  | 
| 265 304 | 
             
            		# New Objects
         | 
| 266 | 
            -
                expect{ C.new. | 
| 267 | 
            -
                C.new. | 
| 268 | 
            -
                D.new. | 
| 269 | 
            -
                D.new. | 
| 270 | 
            -
                E.new. | 
| 271 | 
            -
                E.new. | 
| 305 | 
            +
                expect{ C.new.m1.should == 'foo'}.to raise_error(NoMethodError)  # m1 errors out on C
         | 
| 306 | 
            +
                C.new.m2.should == 'faaxx'
         | 
| 307 | 
            +
                D.new.m1.should == 'fuu' 
         | 
| 308 | 
            +
                D.new.m2.should == 'faaxx'                   # all else is the same...
         | 
| 309 | 
            +
                E.new.m1.should == 'fuuuu' 
         | 
| 310 | 
            +
                E.new.m2.should == 'faaxx'
         | 
| 272 311 | 
             
                # Existing Objects
         | 
| 273 | 
            -
                expect{c. | 
| 274 | 
            -
                c. | 
| 275 | 
            -
                d. | 
| 276 | 
            -
                d. | 
| 277 | 
            -
                e. | 
| 278 | 
            -
                e. | 
| 279 | 
            -
             | 
| 280 | 
            -
             | 
| 312 | 
            +
                expect{c.m1.should == 'foo'}.to raise_error(NoMethodError)   # m1 errors out on C
         | 
| 313 | 
            +
                c.m2.should == 'faaxx'
         | 
| 314 | 
            +
                d.m1.should == 'fuu'
         | 
| 315 | 
            +
                d.m2.should == 'faaxx'
         | 
| 316 | 
            +
                e.m1.should == 'fuuuu'
         | 
| 317 | 
            +
                e.m2.should == 'faaxx'
         | 
| 318 | 
            +
             | 
| 319 | 
            +
            		
         | 
| 320 | 
            +
            		########################################
         | 
| 321 | 
            +
                # more ejection
         | 
| 322 | 
            +
            		########################################
         | 
| 281 323 | 
             
                C.eject :k                                    # eject the only k
         | 
| 282 324 |  | 
| 283 325 | 
             
                C.new.injectors.sym_list.should == []
         | 
| @@ -288,21 +330,24 @@ describe "the inheritance behavior of injectors" do | |
| 288 330 | 
             
                E.injectors.sym_list.should == []
         | 
| 289 331 |  | 
| 290 332 | 
             
            		# New Objects
         | 
| 291 | 
            -
                expect{ C.new. | 
| 292 | 
            -
                expect{ C.new. | 
| 293 | 
            -
                D.new. | 
| 294 | 
            -
                expect{ D.new. | 
| 295 | 
            -
                E.new. | 
| 296 | 
            -
                expect{ E.new. | 
| 333 | 
            +
                expect{ C.new.m1.should == 'foo'}.to raise_error(NoMethodError) 
         | 
| 334 | 
            +
                expect{ C.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) # # faa errors out
         | 
| 335 | 
            +
                D.new.m1.should == 'fuu' 										
         | 
| 336 | 
            +
                expect{ D.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) #faa errors out 
         | 
| 337 | 
            +
                E.new.m1.should == 'fuuuu' 
         | 
| 338 | 
            +
                expect{ E.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) #faa was only available thru k at C 
         | 
| 297 339 | 
             
                # Existing Objects
         | 
| 298 | 
            -
                expect{c. | 
| 299 | 
            -
                expect{c. | 
| 300 | 
            -
                d. | 
| 301 | 
            -
                expect{d. | 
| 302 | 
            -
                e. | 
| 303 | 
            -
                expect{e. | 
| 340 | 
            +
                expect{c.m1.should == 'foo'}.to raise_error(NoMethodError)
         | 
| 341 | 
            +
                expect{c.m2.should == 'faaxx'}.to raise_error(NoMethodError)
         | 
| 342 | 
            +
                d.m1.should == 'fuu'													# same thing for pre-existing objects
         | 
| 343 | 
            +
                expect{d.m2.should == 'faaxx'}.to raise_error(NoMethodError)
         | 
| 344 | 
            +
                e.m1.should == 'fuuuu'
         | 
| 345 | 
            +
                expect{e.m2.should == 'faaxx'}.to raise_error(NoMethodError)
         | 
| 304 346 |  | 
| 305 347 |  | 
| 348 | 
            +
            		########################################
         | 
| 349 | 
            +
                # more ejection
         | 
| 350 | 
            +
            		########################################
         | 
| 306 351 | 
             
                D.eject :j                                    # eject j from D: the only one remaining
         | 
| 307 352 | 
             
                																							# -- everything should revert back to class level
         | 
| 308 353 | 
             
                C.injectors.sym_list.should == []
         | 
| @@ -311,241 +356,263 @@ describe "the inheritance behavior of injectors" do | |
| 311 356 | 
             
                D.new.injectors.sym_list.should == []
         | 
| 312 357 | 
             
                E.injectors.sym_list.should == []
         | 
| 313 358 | 
             
                E.new.injectors.sym_list.should == []
         | 
| 359 | 
            +
            		
         | 
| 314 360 | 
             
            		# New Objects
         | 
| 315 | 
            -
                expect{ C.new. | 
| 316 | 
            -
                expect{ C.new. | 
| 317 | 
            -
                D.new. | 
| 318 | 
            -
                expect{ D.new. | 
| 319 | 
            -
                E.new. | 
| 320 | 
            -
                expect{ E.new. | 
| 361 | 
            +
                expect{ C.new.m1.should == 'foo'}.to raise_error(NoMethodError) # no actual #foo on class 
         | 
| 362 | 
            +
                expect{ C.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) #         ''
         | 
| 363 | 
            +
                D.new.m1.should == 'fuu' 										# retains overrides from D
         | 
| 364 | 
            +
                expect{ D.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) 
         | 
| 365 | 
            +
                E.new.m1.should == 'fuuuu' 									# retains overrides from E
         | 
| 366 | 
            +
                expect{ E.new.m2.should == 'faaxx'}.to raise_error(NoMethodError) 
         | 
| 321 367 | 
             
                # Existing Objects
         | 
| 322 | 
            -
                expect{c. | 
| 323 | 
            -
                expect{c. | 
| 324 | 
            -
                d. | 
| 325 | 
            -
                expect{d. | 
| 326 | 
            -
                e. | 
| 327 | 
            -
                expect{e. | 
| 368 | 
            +
                expect{c.m1.should == 'foo'}.to raise_error(NoMethodError)
         | 
| 369 | 
            +
                expect{c.m2.should == 'faaxx'}.to raise_error(NoMethodError)
         | 
| 370 | 
            +
                d.m1.should == 'fuu'													# same for pre-existing objects
         | 
| 371 | 
            +
                expect{d.m2.should == 'faaxx'}.to raise_error(NoMethodError)
         | 
| 372 | 
            +
                e.m1.should == 'fuuuu'												
         | 
| 373 | 
            +
                expect{e.m2.should == 'faaxx'}.to raise_error(NoMethodError)
         | 
| 328 374 |  | 
| 329 375 | 
             
              end
         | 
| 330 376 |  | 
| 331 | 
            -
             | 
| 377 | 
            +
            	describe 'some special cases' do
         | 
| 378 | 
            +
            		
         | 
| 379 | 
            +
            		the 'behavior when re-applying a new version of same Injector further down the line' do
         | 
| 332 380 |  | 
| 333 | 
            -
             | 
| 381 | 
            +
            			class C1
         | 
| 382 | 
            +
            			end
         | 
| 334 383 |  | 
| 335 | 
            -
             | 
| 384 | 
            +
            			# Define a blanck Injector
         | 
| 336 385 |  | 
| 337 | 
            -
             | 
| 338 | 
            -
            		end
         | 
| 386 | 
            +
            			injector :j1
         | 
| 339 387 |  | 
| 340 | 
            -
            		# Define a Blank Injector
         | 
| 341 388 |  | 
| 342 | 
            -
             | 
| 389 | 
            +
            			# Apply to hierarchy root as defined
         | 
| 343 390 |  | 
| 344 | 
            -
             | 
| 391 | 
            +
            			C1.inject j1	do 															# apply definitions
         | 
| 392 | 
            +
            				def m1                                     
         | 
| 393 | 
            +
            					'm1'                                     
         | 
| 394 | 
            +
            				end                                         
         | 
| 395 | 
            +
            			end                                           
         | 
| 396 | 
            +
            			C1.new.m1.should == 'm1'											# call on Injector
         | 
| 345 397 |  | 
| 346 398 |  | 
| 347 | 
            -
             | 
| 399 | 
            +
            			# DD inherits from CC                         
         | 
| 348 400 |  | 
| 349 | 
            -
             | 
| 350 | 
            -
            			 | 
| 351 | 
            -
             | 
| 352 | 
            -
            			end
         | 
| 353 | 
            -
            		end
         | 
| 401 | 
            +
            			class D1 < C1                                 
         | 
| 402 | 
            +
            			end                                           # call on Injector
         | 
| 403 | 
            +
            			D1.new.m1.should == 'm1'										
         | 
| 354 404 |  | 
| 355 405 |  | 
| 356 | 
            -
             | 
| 406 | 
            +
            			# EE inherits from DD                         
         | 
| 357 407 |  | 
| 358 | 
            -
             | 
| 408 | 
            +
            			class E1 < D1                                 
         | 
| 409 | 
            +
            			end                                           # call on Injector
         | 
| 410 | 
            +
            			E1.new.m1.should == 'm1'										
         | 
| 359 411 |  | 
| 360 412 |  | 
| 361 | 
            -
             | 
| 413 | 
            +
            			############################
         | 
| 414 | 
            +
            			# Re-define methods
         | 
| 415 | 
            +
            			############################
         | 
| 416 | 
            +
            			j1 do 																				# NEW VERSION! because previous had an application
         | 
| 417 | 
            +
            				def m1                                     	# -- was applied to C1 in the hierarchy
         | 
| 418 | 
            +
            					'm1xx'                                   	# Methods only defined in the Virtual Method Cache
         | 
| 419 | 
            +
            				end
         | 
| 420 | 
            +
            			end                                          
         | 
| 362 421 |  | 
| 363 | 
            -
             | 
| 364 | 
            -
             | 
| 365 | 
            -
             | 
| 422 | 
            +
            			# Calls un-affected  !!                       # have existing version
         | 
| 423 | 
            +
             | 
| 424 | 
            +
            			C1.new.m1.should == 'm1'
         | 
| 425 | 
            +
            			D1.new.m1.should == 'm1'
         | 
| 426 | 
            +
            			E1.new.m1.should == 'm1'
         | 
| 366 427 |  | 
| 367 428 |  | 
| 368 | 
            -
             | 
| 429 | 
            +
            			E1.inject j1                      						# apply to hierarchy on E
         | 
| 430 | 
            +
             | 
| 431 | 
            +
            			C1.new.m1.should == 'm1'                  		# same
         | 
| 432 | 
            +
            			D1.new.m1.should == 'm1'                  		# same
         | 
| 433 | 
            +
            			E1.new.m1.should == 'm1xx'                		# changed
         | 
| 369 434 |  | 
| 370 | 
            -
            		class E1 < D1
         | 
| 371 435 | 
             
            		end
         | 
| 372 | 
            -
            		E1.new.m1.should == 'm1'										# inherited call
         | 
| 373 436 |  | 
| 437 | 
            +
            		it 'also passes on this case' do
         | 
| 374 438 |  | 
| 375 | 
            -
             | 
| 376 | 
            -
             | 
| 439 | 
            +
            			class C2
         | 
| 440 | 
            +
            			end                                         
         | 
| 377 441 |  | 
| 378 | 
            -
             | 
| 379 | 
            -
             | 
| 380 | 
            -
             | 
| 442 | 
            +
            			# Define a blank Injector
         | 
| 443 | 
            +
             | 
| 444 | 
            +
            			injector :j2
         | 
| 445 | 
            +
             | 
| 446 | 
            +
             | 
| 447 | 
            +
            			# Apply <full> Injector definition to an ancestor
         | 
| 448 | 
            +
             | 
| 449 | 
            +
            			Object.inject j2 do
         | 
| 450 | 
            +
            				def m1
         | 
| 451 | 
            +
            					'm1xx'
         | 
| 452 | 
            +
            				end
         | 
| 381 453 | 
             
            			end
         | 
| 382 | 
            -
            		end                 
         | 
| 383 | 
            -
            		
         | 
| 384 | 
            -
            		
         | 
| 385 | 
            -
            		# Calls are also re-defined
         | 
| 386 | 
            -
            		                    
         | 
| 387 | 
            -
            		C1.new.m1.should == 'm1xx'                  # call is redefined
         | 
| 388 | 
            -
            		D1.new.m1.should == 'm1xx'                  #      '' 
         | 
| 389 | 
            -
            		E1.new.m1.should == 'm1xx'                  #      ''
         | 
| 390 454 |  | 
| 391 455 |  | 
| 392 | 
            -
             | 
| 456 | 
            +
            			# Call on the Injector
         | 
| 393 457 |  | 
| 394 | 
            -
             | 
| 395 | 
            -
            		
         | 
| 396 | 
            -
            		# calls
         | 
| 458 | 
            +
            			C2.new.m1.should == 'm1xx'                	# call Injector
         | 
| 397 459 |  | 
| 398 | 
            -
             | 
| 399 | 
            -
             | 
| 400 | 
            -
             | 
| 401 | 
            -
             | 
| 402 | 
            -
             | 
| 403 | 
            -
             | 
| 404 | 
            -
             | 
| 405 | 
            -
             | 
| 406 | 
            -
             | 
| 407 | 
            -
            			def m1
         | 
| 408 | 
            -
            				'-----'
         | 
| 460 | 
            +
             | 
| 461 | 
            +
            			############################
         | 
| 462 | 
            +
            			# Re-define methods
         | 
| 463 | 
            +
            			############################
         | 
| 464 | 
            +
             | 
| 465 | 
            +
            			j2 do 																				# NEW VERSION! because previous had an application
         | 
| 466 | 
            +
            				def m1                                      # -- was applied to Object in the hierarchy
         | 
| 467 | 
            +
            					'm1'                                      # Methods only defined in the Virtual Method Cache
         | 
| 468 | 
            +
            				end
         | 
| 409 469 | 
             
            			end
         | 
| 410 | 
            -
            		end
         | 
| 411 | 
            -
            				                  
         | 
| 412 470 |  | 
| 413 | 
            -
             | 
| 471 | 
            +
            			# Calls un-afffected 
         | 
| 414 472 |  | 
| 415 | 
            -
             | 
| 416 | 
            -
             | 
| 417 | 
            -
             | 
| 418 | 
            -
             | 
| 419 | 
            -
             | 
| 420 | 
            -
             | 
| 421 | 
            -
             | 
| 473 | 
            +
            			C2.new.m1.should == 'm1xx'									# still using the previous version --no changes
         | 
| 474 | 
            +
             | 
| 475 | 
            +
             | 
| 476 | 
            +
            			# Inherit
         | 
| 477 | 
            +
             | 
| 478 | 
            +
            			class D2 < C2
         | 
| 479 | 
            +
            			end
         | 
| 480 | 
            +
            			D2.new.m1.should == 'm1xx'									# using previous version
         | 
| 481 | 
            +
             | 
| 482 | 
            +
             | 
| 483 | 
            +
            			# Inherit
         | 
| 422 484 |  | 
| 423 | 
            -
             | 
| 485 | 
            +
            			class E2 < D2
         | 
| 486 | 
            +
            			end
         | 
| 487 | 
            +
            			E2.new.m1.should == 'm1xx'									# using previous version
         | 
| 488 | 
            +
             | 
| 489 | 
            +
             | 
| 490 | 
            +
            			###########################
         | 
| 491 | 
            +
            	    # Finally apply new version
         | 
| 492 | 
            +
            			###########################
         | 
| 493 | 
            +
             | 
| 494 | 
            +
            			C2.inject j2												
         | 
| 495 | 
            +
             | 
| 496 | 
            +
             | 
| 497 | 
            +
            			# Calls changed from C on up
         | 
| 498 | 
            +
             | 
| 499 | 
            +
            			C2.new.m1.should == 'm1'
         | 
| 500 | 
            +
            			D2.new.m1.should == 'm1'
         | 
| 501 | 
            +
            			E2.new.m1.should == 'm1'										# new version of #m1
         | 
| 502 | 
            +
             | 
| 503 | 
            +
             | 
| 504 | 
            +
            			# Call on ancestor the same
         | 
| 505 | 
            +
             | 
| 506 | 
            +
            			Object.new.m1.should == 'm1xx'							# previous version
         | 
| 507 | 
            +
             | 
| 508 | 
            +
             | 
| 509 | 
            +
            			# back to normal
         | 
| 510 | 
            +
             | 
| 511 | 
            +
            			Object.eject j2															# so we do no interfere with other tests!!
         | 
| 424 512 |  | 
| 425 | 
            -
            		class C2
         | 
| 426 513 | 
             
            		end
         | 
| 427 514 |  | 
| 428 | 
            -
            		 | 
| 429 | 
            -
            		
         | 
| 430 | 
            -
            		injector :multi_levelB
         | 
| 431 | 
            -
                
         | 
| 515 | 
            +
            		it 'acts differently when using the Virtual Method Cache (VMC)' do
         | 
| 432 516 |  | 
| 433 | 
            -
             | 
| 434 | 
            -
             | 
| 435 | 
            -
            		C2.inject multi_levelB	do 										# apply definitions
         | 
| 436 | 
            -
            			def m1                                     
         | 
| 437 | 
            -
            				'm1'                                     
         | 
| 438 | 
            -
            			end                                         
         | 
| 439 | 
            -
            		end                                           
         | 
| 440 | 
            -
            		C2.new.m1.should == 'm1'										# call on Injector
         | 
| 517 | 
            +
            			class C3
         | 
| 518 | 
            +
            			end
         | 
| 441 519 |  | 
| 520 | 
            +
            			# Define a Blank Injector
         | 
| 442 521 |  | 
| 443 | 
            -
             | 
| 522 | 
            +
            			injector :j3
         | 
| 444 523 |  | 
| 445 | 
            -
            		class D2 < C2                                 
         | 
| 446 | 
            -
            		end                                           # call on Injector
         | 
| 447 | 
            -
            		D2.new.m1.should == 'm1'										
         | 
| 448 524 |  | 
| 525 | 
            +
            			# Apply the blank injector
         | 
| 449 526 |  | 
| 450 | 
            -
             | 
| 527 | 
            +
            			C3.inject j3													
         | 
| 451 528 |  | 
| 452 | 
            -
            		class E2 < D2                                 
         | 
| 453 | 
            -
            		end                                           # call on Injector
         | 
| 454 | 
            -
            		E2.new.m1.should == 'm1'										
         | 
| 455 529 |  | 
| 456 | 
            -
             | 
| 457 | 
            -
             | 
| 458 | 
            -
             | 
| 459 | 
            -
             | 
| 460 | 
            -
             | 
| 461 | 
            -
            				 | 
| 530 | 
            +
            			# Define function after the application
         | 
| 531 | 
            +
             | 
| 532 | 
            +
            			j3 do 																				# NEW VERSION!
         | 
| 533 | 
            +
            				def m1                                      # -- never applied to Object in the hierarchy
         | 
| 534 | 
            +
            					'm1'                                      # Methods only defined in the Virtual Method Cache
         | 
| 535 | 
            +
            				end
         | 
| 462 536 | 
             
            			end
         | 
| 463 | 
            -
            		end                                          
         | 
| 464 537 |  | 
| 465 | 
            -
            		# Calls un-affected  !!                       # have existing version
         | 
| 466 538 |  | 
| 467 | 
            -
             | 
| 468 | 
            -
            		D2.new.m1.should == 'm1'
         | 
| 469 | 
            -
            		E2.new.m1.should == 'm1'
         | 
| 539 | 
            +
            			# C3 calls
         | 
| 470 540 |  | 
| 471 | 
            -
             | 
| 541 | 
            +
            			C3.new.m1.should == 'm1'											# call works as normal from VMC
         | 
| 472 542 |  | 
| 473 | 
            -
            		C2.new.m1.should == 'm1'                  	# same
         | 
| 474 | 
            -
            		D2.new.m1.should == 'm1'                  	# same
         | 
| 475 | 
            -
            		E2.new.m1.should == 'm1xx'                	# changed
         | 
| 476 543 |  | 
| 477 | 
            -
             | 
| 544 | 
            +
            			# D3 inherits from C3
         | 
| 545 | 
            +
             | 
| 546 | 
            +
            			class D3 < C3
         | 
| 547 | 
            +
            			end
         | 
| 548 | 
            +
            			D3.new.m1.should == 'm1'											# inherited call 
         | 
| 478 549 |  | 
| 479 | 
            -
            	it 'also passes on this case' do
         | 
| 480 | 
            -
                               
         | 
| 481 | 
            -
            		class C3
         | 
| 482 | 
            -
            		end                                         
         | 
| 483 550 |  | 
| 484 | 
            -
             | 
| 485 | 
            -
            		
         | 
| 486 | 
            -
            		injector :multi_levelC
         | 
| 551 | 
            +
            			# E3 inherits from D3
         | 
| 487 552 |  | 
| 488 | 
            -
             | 
| 489 | 
            -
            		# Apply <full> Injector definition to an ancestor
         | 
| 490 | 
            -
            		
         | 
| 491 | 
            -
            		Object.inject multi_levelC do
         | 
| 492 | 
            -
            			def m1
         | 
| 493 | 
            -
            				'm1xx'
         | 
| 553 | 
            +
            			class E3 < D3
         | 
| 494 554 | 
             
            			end
         | 
| 495 | 
            -
             | 
| 496 | 
            -
                
         | 
| 555 | 
            +
            			E3.new.m1.should == 'm1'											# inherited call
         | 
| 497 556 |  | 
| 498 | 
            -
            		# Call on the Injector
         | 
| 499 | 
            -
            		
         | 
| 500 | 
            -
            		C3.new.m1.should == 'm1xx'                	# call Injector
         | 
| 501 557 |  | 
| 558 | 
            +
            			###################################
         | 
| 559 | 
            +
            			# Re-define Virtual Method Cache
         | 
| 560 | 
            +
            			# -- previously un-applied methods
         | 
| 561 | 
            +
            			###################################
         | 
| 502 562 |  | 
| 503 | 
            -
             | 
| 563 | 
            +
            			j3 do 																				# NEW VERSION!
         | 
| 564 | 
            +
            				def m1                                      # -- never applied to Object in the hierarchy
         | 
| 565 | 
            +
            					'm1xx'                                    # Methods only defined in the Virtual Method Cache
         | 
| 566 | 
            +
            				end
         | 
| 567 | 
            +
            			end                 
         | 
| 504 568 |  | 
| 505 | 
            -
             | 
| 506 | 
            -
            			 | 
| 507 | 
            -
             | 
| 569 | 
            +
             | 
| 570 | 
            +
            			# Calls are also re-defined
         | 
| 571 | 
            +
             | 
| 572 | 
            +
            			C3.new.m1.should == 'm1xx'                  	# call is redefined
         | 
| 573 | 
            +
            			D3.new.m1.should == 'm1xx'                  	#      '' 
         | 
| 574 | 
            +
            			E3.new.m1.should == 'm1xx'                  	#      ''
         | 
| 575 | 
            +
             | 
| 576 | 
            +
             | 
| 577 | 
            +
            			# Apply the <full> Injector onto E3
         | 
| 578 | 
            +
             | 
| 579 | 
            +
            			E3.inject j3                      						# Attaches this version onto E only!!
         | 
| 580 | 
            +
             | 
| 581 | 
            +
            			# calls
         | 
| 582 | 
            +
             | 
| 583 | 
            +
            			C3.new.m1.should == 'm1xx'                  	# =>  from cache
         | 
| 584 | 
            +
            			D3.new.m1.should == 'm1xx'                  	#    ''
         | 
| 585 | 
            +
             | 
| 586 | 
            +
            			E3.new.m1.should == 'm1xx'                  	# =>  from applied version
         | 
| 587 | 
            +
             | 
| 588 | 
            +
             | 
| 589 | 
            +
            			################################
         | 
| 590 | 
            +
            			# Re-define cached methods
         | 
| 591 | 
            +
            			#################################
         | 
| 592 | 
            +
             | 
| 593 | 
            +
            			j3 do 																				# NEW VERSION!
         | 
| 594 | 
            +
            				def m1                                      # -- never applied to Object in the hierarchy
         | 
| 595 | 
            +
            					'-----'                                   # Methods only defined in the Virtual Method Cache
         | 
| 596 | 
            +
            				end
         | 
| 508 597 | 
             
            			end
         | 
| 509 | 
            -
            		end
         | 
| 510 | 
            -
            		
         | 
| 511 | 
            -
            		# Calls un-afffected 
         | 
| 512 | 
            -
            		
         | 
| 513 | 
            -
            		C3.new.m1.should == 'm1xx'									# still using the previous version --no changes
         | 
| 514 | 
            -
                    
         | 
| 515 | 
            -
            		
         | 
| 516 | 
            -
            		# Inherit
         | 
| 517 | 
            -
            		
         | 
| 518 | 
            -
            		class D3 < C3
         | 
| 519 | 
            -
            		end
         | 
| 520 | 
            -
            		D3.new.m1.should == 'm1xx'									# using previous version
         | 
| 521 | 
            -
                
         | 
| 522 598 |  | 
| 523 | 
            -
            		# Inherit
         | 
| 524 | 
            -
            		
         | 
| 525 | 
            -
            		class E3 < D3
         | 
| 526 | 
            -
            		end
         | 
| 527 | 
            -
            		E3.new.m1.should == 'm1xx'									# using previous version
         | 
| 528 | 
            -
                         
         | 
| 529 | 
            -
                
         | 
| 530 | 
            -
                # Finally apply new version
         | 
| 531 599 |  | 
| 532 | 
            -
             | 
| 533 | 
            -
            		
         | 
| 534 | 
            -
            		
         | 
| 535 | 
            -
            		# Calls changed from C on up
         | 
| 536 | 
            -
            		
         | 
| 537 | 
            -
            		C3.new.m1.should == 'm1'
         | 
| 538 | 
            -
            		D3.new.m1.should == 'm1'
         | 
| 539 | 
            -
            		E3.new.m1.should == 'm1'										# new version of #m1
         | 
| 600 | 
            +
            			# calls
         | 
| 540 601 |  | 
| 541 | 
            -
             | 
| 542 | 
            -
             | 
| 543 | 
            -
             | 
| 544 | 
            -
             | 
| 602 | 
            +
            			C3.new.m1.should == '-----'									# re-defined!!                  
         | 
| 603 | 
            +
            			D3.new.m1.should == '-----'                 #      ''
         | 
| 604 | 
            +
             | 
| 605 | 
            +
            			E3.new.m1.should == 'm1xx'                  # NOT REDEFINED!!
         | 
| 606 | 
            +
            																									# from applied version
         | 
| 607 | 
            +
             | 
| 608 | 
            +
            		end
         | 
| 545 609 |  | 
| 546 610 | 
             
            	end
         | 
| 611 | 
            +
            end
         | 
| 612 | 
            +
             | 
| 613 | 
            +
            describe "regular Injector internal inheritance" do
         | 
| 547 614 |  | 
| 548 | 
            -
            	it 'carries current methods onto  | 
| 615 | 
            +
            	it 'carries current methods onto Injector Versions/Tags' do
         | 
| 549 616 |  | 
| 550 617 | 
             
            		# Define injector
         | 
| 551 618 |  | 
| @@ -623,6 +690,7 @@ describe "some special cases and circumstances" do | |
| 623 690 | 
             
            		BoomBox.new.on.should == 'Tape playing...Lets make some music'
         | 
| 624 691 | 
             
            		JukeBox.new.on.should == 'CD playing...Lets make some music'
         | 
| 625 692 |  | 
| 693 | 
            +
            		#...                       
         | 
| 626 694 |  | 
| 627 695 | 
             
            		jack :speakers
         | 
| 628 696 |  | 
| @@ -630,170 +698,672 @@ describe "some special cases and circumstances" do | |
| 630 698 | 
             
            			def sound                               
         | 
| 631 699 | 
             
            				super + '...boom boom boom...'        
         | 
| 632 700 | 
             
            			end                                     
         | 
| 633 | 
            -
            		end | 
| 701 | 
            +
            		end                   
         | 
| 702 | 
            +
            		                    
         | 
| 634 703 | 
             
            		JukeBox.inject Bass
         | 
| 635 | 
            -
            		
         | 
| 636 | 
            -
            		#...                       
         | 
| 637 | 
            -
             | 
| 638 704 | 
             
            		JukeBox.new.on.should == 'CD playing...Lets make some music...boom boom boom...'
         | 
| 639 705 |  | 
| 640 706 | 
             
            	end
         | 
| 641 707 |  | 
| 708 | 
            +
             | 
| 642 709 | 
             
            	it 'works accross compound injectors' do
         | 
| 643 710 |  | 
| 644 | 
            -
             | 
| 711 | 
            +
            			jack :S1
         | 
| 645 712 |  | 
| 646 | 
            -
             | 
| 647 | 
            -
             | 
| 648 | 
            -
             | 
| 649 | 
            -
             | 
| 650 | 
            -
            				include jack :s3 do
         | 
| 651 | 
            -
            					def s3m1
         | 
| 713 | 
            +
            			S1 do
         | 
| 714 | 
            +
            				include jack :s2 do
         | 
| 715 | 
            +
            					def s2m1
         | 
| 716 | 
            +
            						:s2m1
         | 
| 652 717 | 
             
            					end
         | 
| 653 | 
            -
            					include jack : | 
| 654 | 
            -
            						def  | 
| 718 | 
            +
            					include jack :s3 do
         | 
| 719 | 
            +
            						def s3m1
         | 
| 720 | 
            +
            							:s3m1
         | 
| 721 | 
            +
            						end
         | 
| 722 | 
            +
            						include jack :s4 do
         | 
| 723 | 
            +
            							def s4m1
         | 
| 724 | 
            +
            								:s4m1
         | 
| 725 | 
            +
            							end
         | 
| 655 726 | 
             
            						end
         | 
| 656 727 | 
             
            					end
         | 
| 657 728 | 
             
            				end
         | 
| 658 729 | 
             
            			end
         | 
| 659 | 
            -
             | 
| 660 | 
            -
             | 
| 661 | 
            -
            		
         | 
| 662 | 
            -
                
         | 
| 663 | 
            -
            		# Apply the injectors
         | 
| 664 | 
            -
            		
         | 
| 665 | 
            -
            		class CompoundContainer
         | 
| 666 | 
            -
            			include S1()
         | 
| 667 | 
            -
            		end
         | 
| 668 | 
            -
            		
         | 
| 669 | 
            -
            		
         | 
| 670 | 
            -
            		# Call on the Injectors
         | 
| 671 | 
            -
            		
         | 
| 672 | 
            -
            		CompoundContainer.new.s2m1
         | 
| 673 | 
            -
            		CompoundContainer.new.s3m1
         | 
| 674 | 
            -
            		CompoundContainer.new.s4m1
         | 
| 730 | 
            +
            			
         | 
| 731 | 
            +
            			S1().s2.s3.s4       													# injector pipeline!
         | 
| 675 732 |  | 
| 676 | 
            -
             | 
| 677 | 
            -
             | 
| 678 | 
            -
             | 
| 679 | 
            -
             | 
| 680 | 
            -
             | 
| 733 | 
            +
             | 
| 734 | 
            +
            			# Apply the injectors
         | 
| 735 | 
            +
             | 
| 736 | 
            +
            			class CompoundContainer
         | 
| 737 | 
            +
            				include S1()
         | 
| 681 738 | 
             
            			end
         | 
| 682 | 
            -
            		end
         | 
| 683 | 
            -
            		CompoundContainer.new.s3m2                  
         | 
| 684 | 
            -
                                     
         | 
| 685 739 |  | 
| 686 | 
            -
             | 
| 740 | 
            +
            			CompoundContainer.new.s2m1.should == :s2m1
         | 
| 741 | 
            +
            			CompoundContainer.new.s3m1.should == :s3m1
         | 
| 742 | 
            +
            			CompoundContainer.new.s4m1.should == :s4m1
         | 
| 743 | 
            +
             | 
| 744 | 
            +
             | 
| 745 | 
            +
            			# Add methods to the VMC of s3
         | 
| 746 | 
            +
             | 
| 747 | 
            +
            			S1().s2.s3 do
         | 
| 748 | 
            +
            				def s3m2
         | 
| 749 | 
            +
            					:s3m2
         | 
| 750 | 
            +
            				end
         | 
| 751 | 
            +
            			end
         | 
| 752 | 
            +
             | 
| 753 | 
            +
            			CompoundContainer.new.s3m2.should == :s3m2
         | 
| 754 | 
            +
             | 
| 755 | 
            +
             | 
| 756 | 
            +
            			# Create a version Tag
         | 
| 757 | 
            +
             | 
| 758 | 
            +
            			AccessTag = S1() 
         | 
| 759 | 
            +
             | 
| 760 | 
            +
            			class SecondContainer
         | 
| 761 | 
            +
            				include AccessTag
         | 
| 762 | 
            +
            			end
         | 
| 763 | 
            +
             | 
| 764 | 
            +
            			SecondContainer.new.s3m2.should == :s3m2
         | 
| 765 | 
            +
            			
         | 
| 766 | 
            +
            	end
         | 
| 767 | 
            +
             | 
| 768 | 
            +
            	it 'works accross the VMC' do
         | 
| 769 | 
            +
             | 
| 770 | 
            +
            		expect{
         | 
| 771 | 
            +
            			
         | 
| 772 | 
            +
            		 	injector :J1
         | 
| 773 | 
            +
            		 	injector :J2
         | 
| 774 | 
            +
            		 	injector :J3
         | 
| 775 | 
            +
             | 
| 776 | 
            +
            			class AA1
         | 
| 777 | 
            +
            			end
         | 
| 778 | 
            +
            			J1 do
         | 
| 779 | 
            +
            				include J2()
         | 
| 780 | 
            +
            			end
         | 
| 781 | 
            +
            			J2 do
         | 
| 782 | 
            +
            				def mJ2						# virtual cache method
         | 
| 783 | 
            +
            					:mJ2
         | 
| 784 | 
            +
            				end
         | 
| 785 | 
            +
            			end
         | 
| 786 | 
            +
            			J1 do
         | 
| 787 | 
            +
            				def mJ1						# applied method
         | 
| 788 | 
            +
            					:mJ1
         | 
| 789 | 
            +
            				end
         | 
| 790 | 
            +
            			end
         | 
| 791 | 
            +
            			class AA1
         | 
| 792 | 
            +
            				include J1()
         | 
| 793 | 
            +
            			end
         | 
| 794 | 
            +
             | 
| 795 | 
            +
            			AA1.new.mJ2.should == :mJ2
         | 
| 796 | 
            +
            			AA1.new.mJ1.should == :mJ1
         | 
| 797 | 
            +
             | 
| 798 | 
            +
            		}.not_to raise_error
         | 
| 687 799 |  | 
| 688 | 
            -
             | 
| 800 | 
            +
            	end 
         | 
| 801 | 
            +
             | 
| 802 | 
            +
            	a 'different example' do
         | 
| 803 | 
            +
             | 
| 804 | 
            +
            		expect{
         | 
| 805 | 
            +
            			
         | 
| 806 | 
            +
            			injector :K1
         | 
| 807 | 
            +
            			injector :K2
         | 
| 808 | 
            +
            			injector :K3
         | 
| 809 | 
            +
             | 
| 810 | 
            +
            			K1 do
         | 
| 811 | 
            +
            			  include K2() do
         | 
| 812 | 
            +
            			    def mj2						# applied method
         | 
| 813 | 
            +
            						:mj2
         | 
| 814 | 
            +
            			    end
         | 
| 815 | 
            +
            			  end
         | 
| 816 | 
            +
            			end
         | 
| 817 | 
            +
            			class AA2
         | 
| 818 | 
            +
            			  include K1()
         | 
| 819 | 
            +
            			end
         | 
| 820 | 
            +
            			AA2.new.mj2.should == :mj2
         | 
| 821 | 
            +
            			K2 do
         | 
| 822 | 
            +
            			  include K3() do
         | 
| 823 | 
            +
            			    def mj3						# virtual cache method with another indirect
         | 
| 824 | 
            +
            						:mj3
         | 
| 825 | 
            +
            			    end
         | 
| 826 | 
            +
            			  end
         | 
| 827 | 
            +
            			end
         | 
| 828 | 
            +
            			AA2.new.mj3.should == :mj3
         | 
| 829 | 
            +
             | 
| 830 | 
            +
            		}.not_to raise_error
         | 
| 689 831 |  | 
| 832 | 
            +
            	end
         | 
| 833 | 
            +
             | 
| 834 | 
            +
            	a 'yet different one' do
         | 
| 835 | 
            +
             | 
| 836 | 
            +
            		expect{
         | 
| 837 | 
            +
            			
         | 
| 838 | 
            +
            			injector :M1
         | 
| 839 | 
            +
            			injector :M2
         | 
| 840 | 
            +
            			injector :M3
         | 
| 841 | 
            +
             | 
| 842 | 
            +
            			M1 do
         | 
| 843 | 
            +
            				include M2() do
         | 
| 844 | 
            +
            					def mk2						# applied method
         | 
| 845 | 
            +
            						:mk2
         | 
| 846 | 
            +
            					end
         | 
| 847 | 
            +
            				end
         | 
| 848 | 
            +
            			end
         | 
| 849 | 
            +
            			class AA3
         | 
| 850 | 
            +
            				include M1()
         | 
| 851 | 
            +
            			end
         | 
| 852 | 
            +
            			AA3.new.mk2.should == :mk2
         | 
| 853 | 
            +
            			M2 do
         | 
| 854 | 
            +
            				include M3()
         | 
| 855 | 
            +
            			end
         | 
| 856 | 
            +
            			M3 do
         | 
| 857 | 
            +
            				def mk3							# virtual cache method
         | 
| 858 | 
            +
            					:mk3
         | 
| 859 | 
            +
            				end
         | 
| 860 | 
            +
            			end
         | 
| 861 | 
            +
            			AA3.new.mk3.should == :mk3
         | 
| 862 | 
            +
             | 
| 863 | 
            +
            		}.not_to raise_error
         | 
| 690 864 |  | 
| 691 | 
            -
             | 
| 865 | 
            +
            	end
         | 
| 866 | 
            +
             | 
| 867 | 
            +
            	describe 'jit inheriatnce' do
         | 
| 868 | 
            +
             | 
| 869 | 
            +
            		before do
         | 
| 870 | 
            +
            			injector :Tagger
         | 
| 871 | 
            +
             | 
| 872 | 
            +
            		end
         | 
| 692 873 |  | 
| 693 | 
            -
            		 | 
| 694 | 
            -
            			 | 
| 874 | 
            +
            		after do
         | 
| 875 | 
            +
            			Tagger(:implode)
         | 
| 876 | 
            +
            			
         | 
| 695 877 | 
             
            		end
         | 
| 696 878 |  | 
| 697 879 |  | 
| 698 | 
            -
            		# Call on tag methods
         | 
| 699 880 |  | 
| 700 | 
            -
            		 | 
| 701 | 
            -
                   
         | 
| 702 | 
            -
                
         | 
| 703 | 
            -
            		# Add methdos to the s2 method cache
         | 
| 881 | 
            +
            		it "follows a just-in-time inheritance policy" do
         | 
| 704 882 |  | 
| 705 | 
            -
             | 
| 706 | 
            -
            			 | 
| 883 | 
            +
            			# 
         | 
| 884 | 
            +
            			# Our Modular Closure
         | 
| 885 | 
            +
            			# 
         | 
| 886 | 
            +
            			Tag1 = Tagger do
         | 
| 887 | 
            +
            				def m1
         | 
| 888 | 
            +
            					1
         | 
| 889 | 
            +
            				end
         | 
| 890 | 
            +
            				
         | 
| 891 | 
            +
            				def m2
         | 
| 892 | 
            +
            					:m2
         | 
| 893 | 
            +
            				end
         | 
| 894 | 
            +
            			end
         | 
| 895 | 
            +
            			
         | 
| 896 | 
            +
            			expect(Tag1.ancestors).to eql( [Tag1] )
         | 
| 897 | 
            +
            			expect(Tagger().ancestors).to eql( [Tagger()] )
         | 
| 898 | 
            +
             | 
| 899 | 
            +
             | 
| 900 | 
            +
            			# 
         | 
| 901 | 
            +
            			# Normal Injector inheritance
         | 
| 902 | 
            +
            			# 
         | 
| 903 | 
            +
            			Tagger do
         | 
| 904 | 
            +
            				def other  					# No overrides No inheritance
         | 
| 905 | 
            +
            					'other'						# -- same ancestors as before
         | 
| 906 | 
            +
            				end 								# -- normal injector inheritance
         | 
| 907 | 
            +
            			end
         | 
| 908 | 
            +
            			
         | 
| 909 | 
            +
            			# test it
         | 
| 910 | 
            +
             | 
| 911 | 
            +
            			expect(Tag1.ancestors).to eql( [Tag1] )
         | 
| 912 | 
            +
            			expect(Tagger().ancestors).to eql( [Tagger()] )
         | 
| 913 | 
            +
            			
         | 
| 914 | 
            +
            			o  = Object.new.extend(Tagger())
         | 
| 915 | 
            +
            			
         | 
| 916 | 
            +
            			# inherited
         | 
| 917 | 
            +
            			o.m1.should == 1
         | 
| 918 | 
            +
            			o.m2.should == :m2
         | 
| 919 | 
            +
            			
         | 
| 920 | 
            +
            			# current
         | 
| 921 | 
            +
            			o.other.should == 'other'
         | 
| 922 | 
            +
            			
         | 
| 923 | 
            +
            			
         | 
| 924 | 
            +
            			#
         | 
| 925 | 
            +
            			# JIT inheritance
         | 
| 926 | 
            +
            			# 
         | 
| 927 | 
            +
            			Tag2 = Tagger do
         | 
| 928 | 
            +
            				def m1							# The :m1 override invokes JIT inheritance
         | 
| 929 | 
            +
            					super + 1					# -- Tag1 is added as ancestor
         | 
| 930 | 
            +
            				end 								# -- allows the use of super
         | 
| 931 | 
            +
            				
         | 
| 932 | 
            +
            				def m3							
         | 
| 933 | 
            +
            					'em3'
         | 
| 934 | 
            +
            				end
         | 
| 935 | 
            +
            			end
         | 
| 936 | 
            +
            			
         | 
| 937 | 
            +
            			# test it
         | 
| 938 | 
            +
            			
         | 
| 939 | 
            +
            			expect(Tagger().ancestors).to eql( [Tagger(), Tag1] )
         | 
| 940 | 
            +
            			expect(Tag2.ancestors).to eql( [Tag2, Tag1] )
         | 
| 941 | 
            +
            			
         | 
| 942 | 
            +
            			p = Object.new.extend(Tag2)
         | 
| 943 | 
            +
            			
         | 
| 944 | 
            +
            			# JIT inherited
         | 
| 945 | 
            +
            			p.m1.should == 2
         | 
| 946 | 
            +
            			
         | 
| 947 | 
            +
            			# regular inheritance
         | 
| 948 | 
            +
            			p.m2.should == :m2
         | 
| 949 | 
            +
            			p.m3.should == 'em3'
         | 
| 950 | 
            +
            			p.other.should == 'other'
         | 
| 951 | 
            +
             | 
| 952 | 
            +
            			
         | 
| 953 | 
            +
            			#
         | 
| 954 | 
            +
            			# Under Inclusion
         | 
| 955 | 
            +
            			# 
         | 
| 956 | 
            +
            			class AA6
         | 
| 957 | 
            +
            				inject Tag2
         | 
| 958 | 
            +
            			end
         | 
| 959 | 
            +
            			aa6 = AA6.new
         | 
| 960 | 
            +
            			
         | 
| 961 | 
            +
            			# test it
         | 
| 962 | 
            +
            			
         | 
| 963 | 
            +
            			aa6.m1.should == 2
         | 
| 964 | 
            +
            			aa6.m2.should == :m2
         | 
| 965 | 
            +
            			aa6.m3.should == 'em3'
         | 
| 966 | 
            +
             | 
| 967 | 
            +
             | 
| 968 | 
            +
            			#
         | 
| 969 | 
            +
            			# One more level: mixed level inheritance
         | 
| 970 | 
            +
            			# 
         | 
| 971 | 
            +
            			Tag3 = 	Tagger() do
         | 
| 972 | 
            +
            				def m1
         | 
| 973 | 
            +
            					super * 2 					# second override to #m1 
         | 
| 974 | 
            +
            				end                   # -- Tag2 added as ancestor
         | 
| 975 | 
            +
            				def m3
         | 
| 976 | 
            +
            					super * 2						# first override to #m3
         | 
| 977 | 
            +
            				end 								
         | 
| 978 | 
            +
            			end
         | 
| 979 | 
            +
            			
         | 
| 980 | 
            +
            			# test it
         | 
| 981 | 
            +
             | 
| 982 | 
            +
            			expect(Tagger().ancestors).to eql( [Tagger(), Tag2, Tag1] )
         | 
| 983 | 
            +
            			expect(Tag3.ancestors).to eql( [Tag3, Tag2, Tag1] )
         | 
| 984 | 
            +
            			expect(Tag2.ancestors).to eql( [Tag2, Tag1] )
         | 
| 985 | 
            +
            			
         | 
| 986 | 
            +
            			class AA7
         | 
| 987 | 
            +
            				inject Tag3 
         | 
| 988 | 
            +
            			end
         | 
| 989 | 
            +
            			aa7 = AA7.new
         | 
| 990 | 
            +
             | 
| 991 | 
            +
            			# JIT inheritance
         | 
| 992 | 
            +
            			aa7.m1.should == 4					
         | 
| 993 | 
            +
            			aa7.m3.should == 'em3em3'
         | 
| 994 | 
            +
            			
         | 
| 995 | 
            +
            			# regular inheritance
         | 
| 996 | 
            +
            			aa7.m2.should == :m2
         | 
| 997 | 
            +
            			aa7.other.should == 'other'
         | 
| 998 | 
            +
             | 
| 999 | 
            +
            			
         | 
| 1000 | 
            +
            			# 
         | 
| 1001 | 
            +
            			# Another version: back to basics
         | 
| 1002 | 
            +
            			# 
         | 
| 1003 | 
            +
            			Tagger() do
         | 
| 1004 | 
            +
            				def m1							# another override but no call to #super
         | 
| 1005 | 
            +
            					:m1								# -- ancestor added
         | 
| 1006 | 
            +
            				end 								
         | 
| 1007 | 
            +
            			end
         | 
| 1008 | 
            +
            			n = Object.new.extend(Tagger())
         | 
| 1009 | 
            +
            			
         | 
| 1010 | 
            +
            			# test it
         | 
| 1011 | 
            +
            			
         | 
| 1012 | 
            +
            			expect(Tagger().ancestors).to eql( [Tagger(), Tag3, Tag2, Tag1] )
         | 
| 1013 | 
            +
            			expect(Tag3.ancestors).to eql( [Tag3, Tag2, Tag1] )
         | 
| 1014 | 
            +
            			expect(Tag2.ancestors).to eql( [Tag2, Tag1] )
         | 
| 1015 | 
            +
            			
         | 
| 1016 | 
            +
            			
         | 
| 1017 | 
            +
            			n.m1.should == :m1		# new version of #m1
         | 
| 1018 | 
            +
            			
         | 
| 1019 | 
            +
            			# JIT
         | 
| 1020 | 
            +
            			n.m3.should == 'em3em3'
         | 
| 1021 | 
            +
            			
         | 
| 1022 | 
            +
            			# regular
         | 
| 1023 | 
            +
            			n.m2.should == :m2
         | 
| 1024 | 
            +
             | 
| 1025 | 
            +
            			
         | 
| 1026 | 
            +
            			# 
         | 
| 1027 | 
            +
            			# Test previous versions
         | 
| 1028 | 
            +
            			# 
         | 
| 1029 | 
            +
            			aa6.m1.should == 2
         | 
| 1030 | 
            +
            			aa6.m2.should == :m2
         | 
| 1031 | 
            +
            			aa6.m3.should == 'em3'
         | 
| 1032 | 
            +
            			
         | 
| 1033 | 
            +
            			aa66 = AA6.new
         | 
| 1034 | 
            +
            			
         | 
| 1035 | 
            +
            			aa66.m1.should == 2
         | 
| 1036 | 
            +
            			aa66.m2.should == :m2
         | 
| 1037 | 
            +
            			aa66.m3.should == 'em3'
         | 
| 1038 | 
            +
             | 
| 1039 | 
            +
            			aa7.m1.should == 4
         | 
| 1040 | 
            +
            			aa7.m2.should == :m2
         | 
| 1041 | 
            +
            			aa7.m3.should == 'em3em3'
         | 
| 1042 | 
            +
             | 
| 1043 | 
            +
            			aa77 = AA7.new
         | 
| 1044 | 
            +
             | 
| 1045 | 
            +
            			aa77.m1.should == 4
         | 
| 1046 | 
            +
            			aa77.m2.should == :m2
         | 
| 1047 | 
            +
            			aa77.m3.should == 'em3em3'
         | 
| 1048 | 
            +
             | 
| 1049 | 
            +
             | 
| 1050 | 
            +
            			#
         | 
| 1051 | 
            +
            			# other clients
         | 
| 1052 | 
            +
            			#
         | 
| 1053 | 
            +
            			class AA6B
         | 
| 1054 | 
            +
            				inject Tag2
         | 
| 1055 | 
            +
            			end
         | 
| 1056 | 
            +
            			aa6b = AA6B.new
         | 
| 1057 | 
            +
            			
         | 
| 1058 | 
            +
            			aa6b.m1.should == 2
         | 
| 1059 | 
            +
            			aa6b.m2.should == :m2
         | 
| 1060 | 
            +
            			aa6b.m3.should == 'em3'
         | 
| 1061 | 
            +
            			
         | 
| 1062 | 
            +
            			#
         | 
| 1063 | 
            +
            			# VMC (Virtual Method Cache) method
         | 
| 1064 | 
            +
            			#
         | 
| 1065 | 
            +
            			Tagger() do
         | 
| 1066 | 
            +
            				def m4							
         | 
| 1067 | 
            +
            					:m4
         | 
| 1068 | 
            +
            				end
         | 
| 707 1069 | 
             
            			end
         | 
| 1070 | 
            +
             | 
| 1071 | 
            +
            			# test it
         | 
| 1072 | 
            +
            			
         | 
| 1073 | 
            +
            			expect(Tagger().ancestors).to eql([Tagger(), Tag3, Tag2, Tag1])
         | 
| 1074 | 
            +
            			expect(Tag3.ancestors).to eql( [Tag3, Tag2, Tag1] )
         | 
| 1075 | 
            +
            			expect(Tag2.ancestors).to eql( [Tag2, Tag1] )
         | 
| 1076 | 
            +
            			
         | 
| 1077 | 
            +
            			aa6b.m1.should == 2
         | 
| 1078 | 
            +
            			aa6b.m2.should == :m2
         | 
| 1079 | 
            +
            			aa6b.m3.should == 'em3'
         | 
| 1080 | 
            +
            			aa6b.m4.should == :m4		# vmc method
         | 
| 1081 | 
            +
            			
         | 
| 1082 | 
            +
            			
         | 
| 1083 | 
            +
            			# Total Tags
         | 
| 1084 | 
            +
            			
         | 
| 1085 | 
            +
            			Tagger().tags.should == [Tag1, Tag2, Tag3]
         | 
| 1086 | 
            +
            			
         | 
| 708 1087 | 
             
            		end
         | 
| 709 1088 |  | 
| 1089 | 
            +
            		it "also allows further ancestor injection" do
         | 
| 1090 | 
            +
            			
         | 
| 1091 | 
            +
            			Tag4 = Tagger do
         | 
| 1092 | 
            +
            				def m1
         | 
| 1093 | 
            +
            					1
         | 
| 1094 | 
            +
            				end
         | 
| 1095 | 
            +
            				def m2
         | 
| 1096 | 
            +
            					:m2
         | 
| 1097 | 
            +
            				end
         | 
| 1098 | 
            +
            			end
         | 
| 710 1099 |  | 
| 711 | 
            -
             | 
| 1100 | 
            +
            			module Mod1
         | 
| 1101 | 
            +
            				def m1
         | 
| 1102 | 
            +
            					'one'
         | 
| 1103 | 
            +
            				end
         | 
| 1104 | 
            +
            			end
         | 
| 712 1105 |  | 
| 713 | 
            -
             | 
| 714 | 
            -
             | 
| 715 | 
            -
             | 
| 716 | 
            -
             | 
| 1106 | 
            +
            			Tag5 = Tagger(Mod1) do
         | 
| 1107 | 
            +
            				
         | 
| 1108 | 
            +
            				# include Mod1											# alternatively
         | 
| 1109 | 
            +
            				
         | 
| 1110 | 
            +
            				def m1
         | 
| 1111 | 
            +
            					super * 2					# invoking inheritance for Tag5 !!
         | 
| 1112 | 
            +
            				end
         | 
| 1113 | 
            +
            				def m3
         | 
| 1114 | 
            +
            					:m3
         | 
| 1115 | 
            +
            				end
         | 
| 1116 | 
            +
            			end
         | 
| 717 1117 |  | 
| 718 | 
            -
             | 
| 1118 | 
            +
            			expect(Tagger().ancestors).to eql([Tagger(), Mod1, Tag4])
         | 
| 1119 | 
            +
            			expect(Tag4.ancestors).to eql([Tag4])
         | 
| 1120 | 
            +
            			expect(Tag5.ancestors).to eql([Tag5, Mod1, Tag4])
         | 
| 719 1121 |  | 
| 720 | 
            -
             | 
| 721 | 
            -
            	 	injector :M2
         | 
| 722 | 
            -
            	 	injector :M3
         | 
| 1122 | 
            +
            			# test it 
         | 
| 723 1123 |  | 
| 724 | 
            -
             | 
| 725 | 
            -
             | 
| 726 | 
            -
             | 
| 727 | 
            -
            			 | 
| 1124 | 
            +
            			Object.new.extend(Tag5).m1.should == 'oneone'
         | 
| 1125 | 
            +
            			Object.new.extend(Tag5).m2.should == :m2
         | 
| 1126 | 
            +
            			Object.new.extend(Tag5).m3.should == :m3
         | 
| 1127 | 
            +
            			
         | 
| 1128 | 
            +
            			# other prolongation
         | 
| 1129 | 
            +
            			
         | 
| 1130 | 
            +
            			Object.new.extend(Tagger(){
         | 
| 1131 | 
            +
            				def m4
         | 
| 1132 | 
            +
            					:m4
         | 
| 1133 | 
            +
            				end
         | 
| 1134 | 
            +
            			}).m4.should == :m4
         | 
| 1135 | 
            +
            			
         | 
| 728 1136 | 
             
            		end
         | 
| 729 | 
            -
            		 | 
| 730 | 
            -
             | 
| 1137 | 
            +
            		
         | 
| 1138 | 
            +
            		it 'also works like this' do
         | 
| 1139 | 
            +
            			
         | 
| 1140 | 
            +
            			Tag6 = Tagger do
         | 
| 1141 | 
            +
            				def m1
         | 
| 1142 | 
            +
            					super() * 2
         | 
| 1143 | 
            +
            				end
         | 
| 1144 | 
            +
            				def m2
         | 
| 1145 | 
            +
            					:m2
         | 
| 1146 | 
            +
            				end
         | 
| 731 1147 | 
             
            			end
         | 
| 732 | 
            -
             | 
| 733 | 
            -
             | 
| 734 | 
            -
             | 
| 1148 | 
            +
            			
         | 
| 1149 | 
            +
            			module Mod2
         | 
| 1150 | 
            +
            				def m1
         | 
| 1151 | 
            +
            					3
         | 
| 1152 | 
            +
            				end
         | 
| 735 1153 | 
             
            			end
         | 
| 1154 | 
            +
            			
         | 
| 1155 | 
            +
            			Object.new.extend(Tagger(Mod2)).m1.should == 6
         | 
| 1156 | 
            +
            			Object.new.extend(Tagger(Mod2)).m2.should == :m2
         | 
| 1157 | 
            +
            			
         | 
| 736 1158 | 
             
            		end
         | 
| 737 | 
            -
            		 | 
| 738 | 
            -
             | 
| 739 | 
            -
             | 
| 740 | 
            -
             | 
| 741 | 
            -
             | 
| 742 | 
            -
             | 
| 743 | 
            -
             | 
| 744 | 
            -
             | 
| 1159 | 
            +
            		
         | 
| 1160 | 
            +
            		this "also possible" do
         | 
| 1161 | 
            +
            			
         | 
| 1162 | 
            +
            			Tag7 = Tagger do
         | 
| 1163 | 
            +
            				def m1
         | 
| 1164 | 
            +
            					1
         | 
| 1165 | 
            +
            				end
         | 
| 1166 | 
            +
            				def m2
         | 
| 1167 | 
            +
            					:m2
         | 
| 1168 | 
            +
            				end
         | 
| 1169 | 
            +
            			end
         | 
| 1170 | 
            +
            			
         | 
| 1171 | 
            +
            			Tag8 = Tagger do
         | 
| 1172 | 
            +
            				def m1
         | 
| 1173 | 
            +
            					super * 2
         | 
| 1174 | 
            +
            				end
         | 
| 1175 | 
            +
            				def m3
         | 
| 1176 | 
            +
            					:m3
         | 
| 1177 | 
            +
            				end
         | 
| 1178 | 
            +
            			end
         | 
| 1179 | 
            +
            			
         | 
| 1180 | 
            +
            			# test it
         | 
| 1181 | 
            +
            		
         | 
| 1182 | 
            +
            			Object.new.extend(Tag8).m1.should == 2
         | 
| 745 1183 |  | 
| 746 | 
            -
            		injector :J1
         | 
| 747 | 
            -
            		injector :J2
         | 
| 748 | 
            -
            		injector :J3
         | 
| 749 1184 |  | 
| 750 | 
            -
             | 
| 751 | 
            -
             | 
| 752 | 
            -
             | 
| 753 | 
            -
             | 
| 754 | 
            -
             | 
| 755 | 
            -
             | 
| 756 | 
            -
             | 
| 757 | 
            -
             | 
| 758 | 
            -
             | 
| 759 | 
            -
             | 
| 760 | 
            -
             | 
| 761 | 
            -
             | 
| 762 | 
            -
             | 
| 763 | 
            -
             | 
| 764 | 
            -
             | 
| 1185 | 
            +
            			#
         | 
| 1186 | 
            +
            			# On the fly overrides
         | 
| 1187 | 
            +
            			# 
         | 
| 1188 | 
            +
            			obj = Object.new.extend(
         | 
| 1189 | 
            +
            				Tagger {
         | 
| 1190 | 
            +
            					def m1
         | 
| 1191 | 
            +
            						super + 3
         | 
| 1192 | 
            +
            					end
         | 
| 1193 | 
            +
            					def m4
         | 
| 1194 | 
            +
            						:m4
         | 
| 1195 | 
            +
            					end
         | 
| 1196 | 
            +
            				})
         | 
| 1197 | 
            +
            			obj.m1.should == 5
         | 
| 1198 | 
            +
            			obj.m2.should == :m2
         | 
| 1199 | 
            +
            			obj.m3.should == :m3
         | 
| 1200 | 
            +
            			obj.m4.should == :m4
         | 
| 1201 | 
            +
            				
         | 
| 765 1202 | 
             
            		end
         | 
| 766 | 
            -
            		 | 
| 767 | 
            -
             | 
| 768 | 
            -
             | 
| 769 | 
            -
             | 
| 770 | 
            -
             | 
| 771 | 
            -
             | 
| 772 | 
            -
             | 
| 773 | 
            -
             | 
| 774 | 
            -
            		 | 
| 775 | 
            -
             | 
| 776 | 
            -
             | 
| 777 | 
            -
             | 
| 778 | 
            -
            				def mk2
         | 
| 1203 | 
            +
            		
         | 
| 1204 | 
            +
            		this "one is a bit tricky" do
         | 
| 1205 | 
            +
            			
         | 
| 1206 | 
            +
            			Tag9 = Tagger do
         | 
| 1207 | 
            +
            				def m1
         | 
| 1208 | 
            +
            					1
         | 
| 1209 | 
            +
            				end
         | 
| 1210 | 
            +
            			end
         | 
| 1211 | 
            +
            		
         | 
| 1212 | 
            +
            			module Mod1
         | 
| 1213 | 
            +
            				def m1
         | 
| 1214 | 
            +
            					'one'
         | 
| 779 1215 | 
             
            				end
         | 
| 780 1216 | 
             
            			end
         | 
| 1217 | 
            +
            			
         | 
| 1218 | 
            +
            			Tag10 = Tagger() do
         | 
| 1219 | 
            +
            				
         | 
| 1220 | 
            +
            				include Mod1
         | 
| 1221 | 
            +
            				
         | 
| 1222 | 
            +
            				def m1
         | 
| 1223 | 
            +
            					super * 2
         | 
| 1224 | 
            +
            				end
         | 
| 1225 | 
            +
            			end
         | 
| 1226 | 
            +
            			
         | 
| 1227 | 
            +
            			# test it
         | 
| 1228 | 
            +
            		
         | 
| 1229 | 
            +
            			Object.new.extend(Tag10).m1.should == 'oneone'
         | 
| 1230 | 
            +
            			Object.new.extend(Tagger()).m1.should == 'oneone'
         | 
| 1231 | 
            +
            			
         | 
| 1232 | 
            +
            			Tag10.ancestors.should == [Tag10, Mod1, Tag9]
         | 
| 1233 | 
            +
            			
         | 
| 781 1234 | 
             
            		end
         | 
| 782 | 
            -
            		 | 
| 783 | 
            -
             | 
| 1235 | 
            +
            		
         | 
| 1236 | 
            +
            		this 'further trick' do
         | 
| 1237 | 
            +
            			
         | 
| 1238 | 
            +
            			Tag11 = Tagger do
         | 
| 1239 | 
            +
            			  def m1
         | 
| 1240 | 
            +
            			    1
         | 
| 1241 | 
            +
            			  end
         | 
| 1242 | 
            +
            			  def m2 							# original definition
         | 
| 1243 | 
            +
            			    2
         | 
| 1244 | 
            +
            			  end
         | 
| 1245 | 
            +
            			end
         | 
| 1246 | 
            +
            			Tag12 = Tagger do
         | 
| 1247 | 
            +
            			  def m1
         | 
| 1248 | 
            +
            			    'm1'
         | 
| 1249 | 
            +
            			  end 								# skipped #m2
         | 
| 1250 | 
            +
            			end
         | 
| 1251 | 
            +
            			Tag13 = Tagger do
         | 
| 1252 | 
            +
            			  def m1
         | 
| 1253 | 
            +
            			    super * 2
         | 
| 1254 | 
            +
            			  end
         | 
| 1255 | 
            +
            			  def m2
         | 
| 1256 | 
            +
            			    super * 2					# override # m2 two levels down
         | 
| 1257 | 
            +
            			  end
         | 
| 1258 | 
            +
            			end
         | 
| 1259 | 
            +
            			class AA10
         | 
| 1260 | 
            +
            			  inject Tag13
         | 
| 1261 | 
            +
            			end
         | 
| 1262 | 
            +
            			
         | 
| 1263 | 
            +
            			# test it
         | 
| 1264 | 
            +
            			
         | 
| 1265 | 
            +
            			AA10.new.m1.should == 'm1m1'
         | 
| 1266 | 
            +
            			AA10.new.m2 == 4
         | 
| 1267 | 
            +
            			
         | 
| 1268 | 
            +
            			Tag13.ancestors.should == [Tag13, Tag12, Tag11]
         | 
| 1269 | 
            +
             | 
| 784 1270 | 
             
            		end
         | 
| 785 | 
            -
            		 | 
| 786 | 
            -
            		 | 
| 787 | 
            -
            			 | 
| 1271 | 
            +
            		
         | 
| 1272 | 
            +
            		it 'rebases' do
         | 
| 1273 | 
            +
            			
         | 
| 1274 | 
            +
            			Tag14 = Tagger do
         | 
| 1275 | 
            +
            				def m1
         | 
| 1276 | 
            +
            					1
         | 
| 1277 | 
            +
            				end
         | 
| 1278 | 
            +
            			end
         | 
| 1279 | 
            +
            			
         | 
| 1280 | 
            +
            			class AA11
         | 
| 1281 | 
            +
            				inject Tagger() do
         | 
| 1282 | 
            +
            					def m1
         | 
| 1283 | 
            +
            						super + 1
         | 
| 1284 | 
            +
            					end
         | 
| 1285 | 
            +
            				end
         | 
| 1286 | 
            +
            			end
         | 
| 1287 | 
            +
            			
         | 
| 1288 | 
            +
            			# test it
         | 
| 1289 | 
            +
            			
         | 
| 1290 | 
            +
            			AA11.new.m1.should == 2
         | 
| 1291 | 
            +
            			
         | 
| 1292 | 
            +
            			
         | 
| 1293 | 
            +
            			Tag15 = Tagger do
         | 
| 1294 | 
            +
            				def m1
         | 
| 1295 | 
            +
            					5									# rebase m1
         | 
| 1296 | 
            +
            				end
         | 
| 1297 | 
            +
            			end
         | 
| 1298 | 
            +
            			
         | 
| 1299 | 
            +
            			class BB11
         | 
| 1300 | 
            +
            				inject Tagger() do
         | 
| 1301 | 
            +
            					def m1
         | 
| 1302 | 
            +
            						super * 2				# new override
         | 
| 1303 | 
            +
            					end
         | 
| 1304 | 
            +
            				end
         | 
| 1305 | 
            +
            			end
         | 
| 1306 | 
            +
            			
         | 
| 1307 | 
            +
            			# test it
         | 
| 1308 | 
            +
            			
         | 
| 1309 | 
            +
            			BB11.new.m1.should == 10
         | 
| 1310 | 
            +
            			
         | 
| 1311 | 
            +
            			
         | 
| 788 1312 | 
             
            		end
         | 
| 789 | 
            -
            		 | 
| 790 | 
            -
             | 
| 1313 | 
            +
            		
         | 
| 1314 | 
            +
            		it 'takes Injector Directives' do
         | 
| 1315 | 
            +
            			
         | 
| 1316 | 
            +
            			Tag16 = Tagger do
         | 
| 1317 | 
            +
            				def m1
         | 
| 1318 | 
            +
            					1
         | 
| 1319 | 
            +
            				end
         | 
| 1320 | 
            +
            			end
         | 
| 1321 | 
            +
            			
         | 
| 1322 | 
            +
            			class AA12
         | 
| 1323 | 
            +
            				inject Tagger() do
         | 
| 1324 | 
            +
            					def m1
         | 
| 1325 | 
            +
            						super + 1
         | 
| 1326 | 
            +
            					end
         | 
| 1327 | 
            +
            				end
         | 
| 791 1328 | 
             
            			end
         | 
| 1329 | 
            +
            			
         | 
| 1330 | 
            +
            			AA12.new.m1.should == 2
         | 
| 1331 | 
            +
            			
         | 
| 1332 | 
            +
            			
         | 
| 1333 | 
            +
            			Tag17 = Tagger do
         | 
| 1334 | 
            +
            				def m1
         | 
| 1335 | 
            +
            					5									# rebase m1
         | 
| 1336 | 
            +
            				end
         | 
| 1337 | 
            +
            			end
         | 
| 1338 | 
            +
            			
         | 
| 1339 | 
            +
            			class BB12
         | 
| 1340 | 
            +
            				inject Tagger() do
         | 
| 1341 | 
            +
            					def m1
         | 
| 1342 | 
            +
            						super * 2				# new override
         | 
| 1343 | 
            +
            					end
         | 
| 1344 | 
            +
            				end
         | 
| 1345 | 
            +
            			end
         | 
| 1346 | 
            +
            			
         | 
| 1347 | 
            +
            			BB12.new.m1.should == 10
         | 
| 1348 | 
            +
            			
         | 
| 1349 | 
            +
            			# test directives
         | 
| 1350 | 
            +
            			
         | 
| 1351 | 
            +
            			Tagger(:silence)
         | 
| 1352 | 
            +
             | 
| 1353 | 
            +
            			AA12.new.m1.should == nil										# both bases affected
         | 
| 1354 | 
            +
            			BB12.new.m1.should == nil
         | 
| 1355 | 
            +
            			
         | 
| 1356 | 
            +
            			Tagger(:active)
         | 
| 1357 | 
            +
            			
         | 
| 1358 | 
            +
            			AA12.new.m1.should == 2											# both bases restored
         | 
| 1359 | 
            +
            			BB12.new.m1.should == 10
         | 
| 1360 | 
            +
            			
         | 
| 792 1361 | 
             
            		end
         | 
| 793 1362 |  | 
| 794 | 
            -
            		AA3.new.mk3
         | 
| 795 | 
            -
             | 
| 796 1363 | 
             
            	end
         | 
| 797 | 
            -
             | 
| 798 1364 | 
             
            end
         | 
| 799 1365 |  | 
| 1366 | 
            +
            # profile = RubyProf.stop
         | 
| 1367 | 
            +
            # RubyProf::FlatPrinter.new(profile).print(STDOUT)
         | 
| 1368 | 
            +
            # RubyProf::GraphHtmlPrinter.new(profile).print(open('profile.html', 'w+'))
         | 
| 1369 | 
            +
            # RubyProf::CallStackPrinter.new(profile).print(open('profile.html', 'w+'))
         |