Changeset 4060
- Timestamp:
- 03/27/06 05:13:46 (3 years ago)
- Files:
-
- trunk/activesupport/CHANGELOG (modified) (1 diff)
- trunk/activesupport/lib/active_support/core_ext/module.rb (modified) (1 diff)
- trunk/activesupport/lib/active_support/core_ext/module/introspection.rb (added)
- trunk/activesupport/lib/active_support/core_ext/module/loading.rb (added)
- trunk/activesupport/lib/active_support/dependencies.rb (modified) (2 diffs)
- trunk/activesupport/test/autoloading_fixtures/module_folder (added)
- trunk/activesupport/test/autoloading_fixtures/module_folder/nested_class.rb (added)
- trunk/activesupport/test/autoloading_fixtures/module_folder/nested_sibling.rb (added)
- trunk/activesupport/test/core_ext/module_test.rb (modified) (1 diff)
- trunk/activesupport/test/dependencies_test.rb (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/activesupport/CHANGELOG
r4059 r4060 1 1 *SVN* 2 3 * When possible, avoid incorrectly obtaining constants from parent modules. Fixes #4221. [Nicholas Seckar] 4 5 * Add more tests for dependencies; refactor existing cases. [Nicholas Seckar] 6 7 * Move Module#parent and Module#as_load_path into core_ext. Add Module#parent. [Nicholas Seckar] 2 8 3 9 * Add CachingTools::HashCaching to simplify the creation of nested, autofilling hashes. [Nicholas Seckar] trunk/activesupport/lib/active_support/core_ext/module.rb
r3535 r4060 2 2 require File.dirname(__FILE__) + '/module/attribute_accessors' 3 3 require File.dirname(__FILE__) + '/module/delegation' 4 require File.dirname(__FILE__) + '/module/introspection' 5 require File.dirname(__FILE__) + '/module/loading' trunk/activesupport/lib/active_support/dependencies.rb
r3668 r4060 79 79 alias :rails_original_const_missing :const_missing 80 80 81 def parent82 parent_name = name.split('::')[0..-2] * '::'83 parent_name.empty? ? Object : parent_name.constantize84 end85 86 def as_load_path87 if self == Object || self == Kernel88 ''89 elsif is_a? Class90 parent == self ? '' : parent.as_load_path91 else92 name.split('::').collect do |word|93 word.underscore94 end * '/'95 end96 end97 98 81 # Use const_missing to autoload associations so we don't have to 99 82 # require_association when using single-table inheritance. … … 117 100 end 118 101 119 if parent && parent != self 102 # Attempt to access the name from the parent, unless we don't have a valid 103 # parent, or the constant is already defined in the parent. If the latter 104 # is the case, then we are being queried via self::class_id, and we should 105 # avoid returning the constant from the parent if possible. 106 if parent && parent != self && ! parents.any? { |p| p.const_defined?(class_id) } 120 107 suppress(NameError) do 121 108 return parent.send(:const_missing, class_id) trunk/activesupport/test/core_ext/module_test.rb
r3535 r4060 83 83 assert_raises(ArgumentError) { eval($noplace) } 84 84 end 85 86 def test_parent 87 assert_equal Yz::Zy, Yz::Zy::Cd.parent 88 assert_equal Yz, Yz::Zy.parent 89 assert_equal Object, Yz.parent 90 end 91 92 def test_parents 93 assert_equal [Yz::Zy, Yz, Object], Yz::Zy::Cd.parents 94 assert_equal [Yz, Object], Yz::Zy.parents 95 end 96 97 def test_as_load_path 98 assert_equal 'yz/zy', Yz::Zy.as_load_path 99 assert_equal 'yz', Yz.as_load_path 100 end 85 101 end trunk/activesupport/test/dependencies_test.rb
r3537 r4060 7 7 def teardown 8 8 Dependencies.clear 9 end 10 11 def with_loading(from_dir = nil) 12 prior_path = $LOAD_PATH.clone 13 $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/#{from_dir}" if from_dir 14 old_mechanism, Dependencies.mechanism = Dependencies.mechanism, :load 15 yield 16 ensure 17 $LOAD_PATH.clear 18 $LOAD_PATH.concat prior_path 19 Dependencies.mechanism = old_mechanism 9 20 end 10 21 … … 30 41 31 42 def test_dependency_which_raises_exception_isnt_added_to_loaded_set 32 old_mechanism, Dependencies.mechanism = Dependencies.mechanism, :load 43 with_loading do 44 filename = "#{File.dirname(__FILE__)}/dependencies/raises_exception" 45 $raises_exception_load_count = 0 33 46 34 filename = "#{File.dirname(__FILE__)}/dependencies/raises_exception" 35 $raises_exception_load_count = 0 47 5.times do |count| 48 assert_raises(RuntimeError) { require_dependency filename } 49 assert_equal count + 1, $raises_exception_load_count 36 50 37 5.times do |count| 38 assert_raises(RuntimeError) { require_dependency filename } 39 assert_equal count + 1, $raises_exception_load_count 51 assert !Dependencies.loaded.include?(filename) 52 assert !Dependencies.history.include?(filename) 53 end 54 end 55 end 56 57 def test_warnings_should_be_enabled_on_first_load 58 with_loading do 59 old_warnings, Dependencies.warnings_on_first_load = Dependencies.warnings_on_first_load, true 60 61 filename = "#{File.dirname(__FILE__)}/dependencies/check_warnings" 62 $check_warnings_load_count = 0 40 63 41 64 assert !Dependencies.loaded.include?(filename) 42 65 assert !Dependencies.history.include?(filename) 66 67 silence_warnings { require_dependency filename } 68 assert_equal 1, $check_warnings_load_count 69 assert_equal true, $checked_verbose, 'On first load warnings should be enabled.' 70 71 assert Dependencies.loaded.include?(filename) 72 Dependencies.clear 73 assert !Dependencies.loaded.include?(filename) 74 assert Dependencies.history.include?(filename) 75 76 silence_warnings { require_dependency filename } 77 assert_equal 2, $check_warnings_load_count 78 assert_equal nil, $checked_verbose, 'After first load warnings should be left alone.' 79 80 assert Dependencies.loaded.include?(filename) 81 Dependencies.clear 82 assert !Dependencies.loaded.include?(filename) 83 assert Dependencies.history.include?(filename) 84 85 enable_warnings { require_dependency filename } 86 assert_equal 3, $check_warnings_load_count 87 assert_equal true, $checked_verbose, 'After first load warnings should be left alone.' 88 89 assert Dependencies.loaded.include?(filename) 43 90 end 44 ensure45 Dependencies.mechanism = old_mechanism46 end47 48 def test_warnings_should_be_enabled_on_first_load49 old_mechanism, Dependencies.mechanism = Dependencies.mechanism, :load50 old_warnings, Dependencies.warnings_on_first_load = Dependencies.warnings_on_first_load, true51 52 filename = "#{File.dirname(__FILE__)}/dependencies/check_warnings"53 $check_warnings_load_count = 054 55 assert !Dependencies.loaded.include?(filename)56 assert !Dependencies.history.include?(filename)57 58 silence_warnings { require_dependency filename }59 assert_equal 1, $check_warnings_load_count60 assert_equal true, $checked_verbose, 'On first load warnings should be enabled.'61 62 assert Dependencies.loaded.include?(filename)63 Dependencies.clear64 assert !Dependencies.loaded.include?(filename)65 assert Dependencies.history.include?(filename)66 67 silence_warnings { require_dependency filename }68 assert_equal 2, $check_warnings_load_count69 assert_equal nil, $checked_verbose, 'After first load warnings should be left alone.'70 71 assert Dependencies.loaded.include?(filename)72 Dependencies.clear73 assert !Dependencies.loaded.include?(filename)74 assert Dependencies.history.include?(filename)75 76 enable_warnings { require_dependency filename }77 assert_equal 3, $check_warnings_load_count78 assert_equal true, $checked_verbose, 'After first load warnings should be left alone.'79 80 assert Dependencies.loaded.include?(filename)81 ensure82 Dependencies.mechanism = old_mechanism83 Dependencies.warnings_on_first_load = old_warnings84 91 end 85 92 86 93 def test_mutual_dependencies_dont_infinite_loop 87 $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/dependencies" 88 old_mechanism, Dependencies.mechanism = Dependencies.mechanism, :load 94 with_loading 'dependencies' do 95 $mutual_dependencies_count = 0 96 assert_nothing_raised { require_dependency 'mutual_one' } 97 assert_equal 2, $mutual_dependencies_count 89 98 90 $mutual_dependencies_count = 0 91 assert_nothing_raised { require_dependency 'mutual_one' } 92 assert_equal 2, $mutual_dependencies_count 99 Dependencies.clear 93 100 94 Dependencies.clear 95 96 $mutual_dependencies_count = 0 97 assert_nothing_raised { require_dependency 'mutual_two' } 98 assert_equal 2, $mutual_dependencies_count 99 ensure 100 $LOAD_PATH.shift 101 Dependencies.mechanism = old_mechanism 101 $mutual_dependencies_count = 0 102 assert_nothing_raised { require_dependency 'mutual_two' } 103 assert_equal 2, $mutual_dependencies_count 104 end 102 105 end 103 106 … … 107 110 108 111 def test_module_loading 109 begin 110 $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/autoloading_fixtures" 111 old_mechanism, Dependencies.mechanism = Dependencies.mechanism, :load 112 112 with_loading 'autoloading_fixtures' do 113 113 assert_kind_of Module, A 114 114 assert_kind_of Class, A::B 115 115 assert_kind_of Class, A::C::D 116 116 assert_kind_of Class, A::C::E::F 117 ensure118 $LOAD_PATH.shift119 Dependencies.mechanism = old_mechanism120 117 end 121 118 end 122 119 123 def test_non_existing_cost_raises_nameerrror 124 begin 125 $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/autoloading_fixtures" 126 old_mechanism, Dependencies.mechanism = Dependencies.mechanism, :load 127 assert_raises(NameError) do 128 DoesNotExist 129 end 130 131 assert_raises(NameError) do 132 NoModule::DoesNotExist 133 end 134 135 assert_raises(NameError) do 136 A::DoesNotExist 137 end 138 139 assert_raises(NameError) do 140 A::B::DoesNotExist 141 end 142 ensure 143 $LOAD_PATH.shift 144 Dependencies.mechanism = old_mechanism 120 def test_non_existing_const_raises_name_error 121 with_loading 'autoloading_fixtures' do 122 assert_raises(NameError) { DoesNotExist } 123 assert_raises(NameError) { NoModule::DoesNotExist } 124 assert_raises(NameError) { A::DoesNotExist } 125 assert_raises(NameError) { A::B::DoesNotExist } 145 126 end 146 147 127 end 128 129 def test_directories_should_manifest_as_modules 130 with_loading 'autoloading_fixtures' do 131 assert_kind_of Module, ModuleFolder 132 Object.send :remove_const, :ModuleFolder 133 end 134 end 135 136 def test_nested_class_access 137 with_loading 'autoloading_fixtures' do 138 assert_kind_of Class, ModuleFolder::NestedClass 139 Object.send :remove_const, :ModuleFolder 140 end 141 end 142 143 def test_nested_class_can_access_sibling 144 with_loading 'autoloading_fixtures' do 145 sibling = ModuleFolder::NestedClass.class_eval "NestedSibling" 146 assert defined?(ModuleFolder::NestedSibling) 147 assert_equal ModuleFolder::NestedSibling, sibling 148 Object.send :remove_const, :ModuleFolder 149 end 150 end 151 152 def failing_test_access_thru_and_upwards_fails 153 with_loading 'autoloading_fixtures' do 154 assert ! defined?(ModuleFolder) 155 assert_raises(NameError) { ModuleFolder::Object } 156 assert_raises(NameError) { ModuleFolder::NestedClass::Object } 157 Object.send :remove_const, :ModuleFolder 158 end 159 end 160 148 161 end