aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2012-08-28 20:27:59 +0200
committerXavier Noria <fxn@hashref.com>2012-08-28 20:34:39 +0200
commitb33700f5580b4cd85379a1dc60fa341ac4d8deb2 (patch)
tree8c531e63fa5f14282def9d7dfd30589584d3329f /activesupport
parent844e944465beb37bd19bdfdedc19eba54479f39e (diff)
downloadrails-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.rb15
-rw-r--r--activesupport/test/autoloading_fixtures/circular1.rb6
-rw-r--r--activesupport/test/autoloading_fixtures/circular2.rb4
-rw-r--r--activesupport/test/dependencies_test.rb6
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