Changeset 5307
- Timestamp:
- 10/15/06 23:32:31 (2 years ago)
- Files:
-
- trunk/activesupport/CHANGELOG (modified) (1 diff)
- trunk/activesupport/lib/active_support/dependencies.rb (modified) (7 diffs)
- trunk/activesupport/test/dependencies_test.rb (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/activesupport/CHANGELOG
r5287 r5307 1 1 *SVN* 2 3 * Add 'unloadable', a method used to mark any constant as requiring an unload after each request. [Nicholas Seckar] 2 4 3 5 * Make core_ext/string/access.rb multibyte safe. Closes #6388 [Manfred Stienstra] trunk/activesupport/lib/active_support/dependencies.rb
r5303 r5307 39 39 self.autoloaded_constants = [] 40 40 41 # An array of constant names that need to be unloaded on every request. Used 42 # to allow arbitrary constants to be marked for unloading. 43 mattr_accessor :explicitly_unloadable_constants 44 self.explicitly_unloadable_constants = [] 45 41 46 # Set to true to enable logging of const_missing and file loads 42 47 mattr_accessor :log_activity … … 61 66 log_call 62 67 loaded.clear 63 remove_ autoloaded_constants!68 remove_unloadable_constants! 64 69 end 65 70 … … 253 258 end 254 259 255 # Remove the constants that have been autoloaded. 256 def remove_autoloaded_constants! 257 until autoloaded_constants.empty? 258 const = autoloaded_constants.shift 259 next unless qualified_const_defined? const 260 names = const.split('::') 261 if names.size == 1 || names.first.empty? # It's under Object 262 parent = Object 263 else 264 parent = (names[0..-2] * '::').constantize 265 end 266 log "removing constant #{const}" 267 parent.send :remove_const, names.last 268 true 269 end 260 # Remove the constants that have been autoloaded, and those that have been 261 # marked for unloading. 262 def remove_unloadable_constants! 263 autoloaded_constants.each { |const| remove_constant const } 264 autoloaded_constants.clear 265 explicitly_unloadable_constants.each { |const| remove_constant const } 270 266 end 271 267 … … 275 271 return false unless qualified_const_defined? name 276 272 return autoloaded_constants.include?(name) 273 end 274 275 # Will the provided constant descriptor be unloaded? 276 def will_unload?(const_desc) 277 autoloaded?(desc) || 278 explicitly_unloadable_constants.include?(to_constant_name(const_desc)) 279 end 280 281 # Mark the provided constant name for unloading. This constant will be 282 # unloaded on each request, not just the next one. 283 def mark_for_unload(const_desc) 284 name = to_constant_name const_desc 285 if explicitly_unloadable_constants.include? name 286 return false 287 else 288 explicitly_unloadable_constants << name 289 return true 290 end 277 291 end 278 292 … … 296 310 when String then desc.starts_with?('::') ? desc[2..-1] : desc 297 311 when Symbol then desc.to_s 298 when Module then desc.name 312 when Module 313 raise ArgumentError, "Anonymous modules have no name to be referenced by" if desc.name.blank? 314 desc.name 299 315 else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}" 300 316 end 317 end 318 319 def remove_constant(const) 320 return false unless qualified_const_defined? const 321 322 names = const.split('::') 323 if names.size == 1 || names.first.empty? # It's under Object 324 parent = Object 325 else 326 parent = (names[0..-2] * '::').constantize 327 end 328 329 log "removing constant #{const}" 330 parent.send :remove_const, names.last 331 return true 301 332 end 302 333 … … 329 360 Dependencies.load_missing_constant self, class_id 330 361 end 362 363 def unloadable(const_desc = self) 364 super(const_desc) 365 end 366 331 367 end 332 368 … … 367 403 raise 368 404 end 405 406 # Mark the given constant as unloadable. Unloadable constants are removed each 407 # time dependencies are cleared. 408 # 409 # Note that marking a constant for unloading need only be done once. Setup 410 # or init scripts may list each unloadable constant that may need unloading; 411 # each constant will be removed for every subsequent clear, as opposed to for 412 # the first clear. 413 # 414 # The provided constant descriptor may be a (non-anonymous) module or class, 415 # or a qualified constant name as a string or symbol. 416 # 417 # Returns true if the constant was not previously marked for unloading, false 418 # otherwise. 419 def unloadable(const_desc) 420 Dependencies.mark_for_unload const_desc 421 end 422 369 423 end 370 424 trunk/activesupport/test/dependencies_test.rb
r5053 r5307 25 25 Dependencies.load_paths = prior_load_paths 26 26 Dependencies.mechanism = old_mechanism 27 Dependencies.explicitly_unloadable_constants = [] 27 28 end 28 29 … … 454 455 end 455 456 457 def test_unloadable 458 with_loading 'autoloading_fixtures' do 459 Object.const_set :M, Module.new 460 M.unloadable 461 462 Dependencies.clear 463 assert ! defined?(M) 464 465 Object.const_set :M, Module.new 466 Dependencies.clear 467 assert ! defined?(M), "Dependencies should unload unloadable constants each time" 468 end 469 end 470 471 def test_unloadable_should_fail_with_anonymous_modules 472 with_loading 'autoloading_fixtures' do 473 m = Module.new 474 assert_raises(ArgumentError) { m.unloadable } 475 end 476 end 477 478 def test_unloadable_should_return_change_flag 479 with_loading 'autoloading_fixtures' do 480 Object.const_set :M, Module.new 481 assert_equal true, M.unloadable 482 assert_equal false, M.unloadable 483 end 484 end 485 456 486 end