diff options
author | Xavier Noria <fxn@hashref.com> | 2012-08-28 20:27:59 +0200 |
---|---|---|
committer | Xavier Noria <fxn@hashref.com> | 2012-08-28 20:34:39 +0200 |
commit | b33700f5580b4cd85379a1dc60fa341ac4d8deb2 (patch) | |
tree | 8c531e63fa5f14282def9d7dfd30589584d3329f /activesupport | |
parent | 844e944465beb37bd19bdfdedc19eba54479f39e (diff) | |
download | rails-b33700f5580b4cd85379a1dc60fa341ac4d8deb2.tar.gz rails-b33700f5580b4cd85379a1dc60fa341ac4d8deb2.tar.bz2 rails-b33700f5580b4cd85379a1dc60fa341ac4d8deb2.zip |
detect circular constant autoloading
Nowadays circular autoloads do not work, but the user gets a NameError
that says some constant is undefined. That's puzzling, because he is
normally trying to autoload a constant he knows can be autoloaded.
With this check we can give a better error message.
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/lib/active_support/dependencies.rb | 15 | ||||
-rw-r--r-- | activesupport/test/autoloading_fixtures/circular1.rb | 6 | ||||
-rw-r--r-- | activesupport/test/autoloading_fixtures/circular2.rb | 4 | ||||
-rw-r--r-- | activesupport/test/dependencies_test.rb | 6 |
4 files changed, 27 insertions, 4 deletions
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 26545d8553..d2afea2545 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -479,10 +479,17 @@ module ActiveSupport #:nodoc: file_path = search_for_file(path_suffix) - if file_path && ! loaded.include?(File.expand_path(file_path).sub(/\.rb\z/, '')) # We found a matching file to load - require_or_load file_path - raise LoadError, "Expected #{file_path} to define #{qualified_name}" unless from_mod.const_defined?(const_name, false) - return from_mod.const_get(const_name) + if file_path + expanded = File.expand_path(file_path) + expanded.sub!(/\.rb/, '') + + if loaded.include?(expanded) + raise "Circular dependency detected while autoloading constant #{qualified_name}" + else + require_or_load(expanded) + raise LoadError, "Expected #{file_path} to define #{qualified_name}" unless from_mod.const_defined?(const_name, false) + return from_mod.const_get(const_name) + end elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix) return mod elsif (parent = from_mod.parent) && parent != from_mod && diff --git a/activesupport/test/autoloading_fixtures/circular1.rb b/activesupport/test/autoloading_fixtures/circular1.rb new file mode 100644 index 0000000000..a45761f066 --- /dev/null +++ b/activesupport/test/autoloading_fixtures/circular1.rb @@ -0,0 +1,6 @@ +silence_warnings do + Circular2 +end + +class Circular1 +end diff --git a/activesupport/test/autoloading_fixtures/circular2.rb b/activesupport/test/autoloading_fixtures/circular2.rb new file mode 100644 index 0000000000..c847fa5001 --- /dev/null +++ b/activesupport/test/autoloading_fixtures/circular2.rb @@ -0,0 +1,4 @@ +Circular1 + +class Circular2 +end diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index f1da6378a7..e5bc806397 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -145,6 +145,12 @@ class DependenciesTest < ActiveSupport::TestCase end end + def test_circular_autoloading_detection + with_autoloading_fixtures do + assert_raise(RuntimeError, "Circular dependency detected while autoloading constant Circular1") { Circular1 } + end + end + def test_module_loading with_autoloading_fixtures do assert_kind_of Module, A |