aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/dependencies.rb
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2013-12-06 19:13:51 +0100
committerXavier Noria <fxn@hashref.com>2013-12-06 19:18:10 +0100
commit01c9782fa2392729bea08409e348fe049857d9d6 (patch)
treed4ef12c78ce6e98e77093e36573bf1c7728012e6 /activesupport/lib/active_support/dependencies.rb
parent8ef1ef1b822cdb49e72edd16a8ddbc67e5e1cf94 (diff)
downloadrails-01c9782fa2392729bea08409e348fe049857d9d6.tar.gz
rails-01c9782fa2392729bea08409e348fe049857d9d6.tar.bz2
rails-01c9782fa2392729bea08409e348fe049857d9d6.zip
better error message for constants autoloaded from anonymous modules [fixes #13204]
load_missing_constant is a private method that basically plays the role of const_missing. This method has an error condition that is surprising: it raises if the class or module already has the missing constant. How is it possible that if the class of module has the constant Ruby has called const_missing in the first place? The answer is that the from_mod argument is self except for anonymous modules, because const_missing passes down Object in such case (see the comment in the source code of the patch for the rationale). But then, it is better to pass down Object *if Object is also missing the constant* and otherwise err with an informative message right away.
Diffstat (limited to 'activesupport/lib/active_support/dependencies.rb')
-rw-r--r--activesupport/lib/active_support/dependencies.rb20
1 files changed, 13 insertions, 7 deletions
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 19d4ff51d7..6be19771f5 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -176,14 +176,22 @@ module ActiveSupport #:nodoc:
end
def const_missing(const_name)
- # The interpreter does not pass nesting information, and in the
- # case of anonymous modules we cannot even make the trade-off of
- # assuming their name reflects the nesting. Resort to Object as
- # the only meaningful guess we can make.
- from_mod = anonymous? ? ::Object : self
+ from_mod = anonymous? ? guess_for_anonymous(const_name) : self
Dependencies.load_missing_constant(from_mod, const_name)
end
+ # Dependencies assumes the name of the module reflects the nesting (unless
+ # it can be proven that is not the case), and the path to the file that
+ # defines the constant. Anonymous modules cannot follow these conventions
+ # and we assume therefore the user wants to refer to a top-level constant.
+ def guess_for_anonymous(const_name)
+ if Object.const_defined?(const_name)
+ raise NameError, "#{const_name} cannot be autoloaded from an anonymous class or module"
+ else
+ Object
+ end
+ end
+
def unloadable(const_desc = self)
super(const_desc)
end
@@ -456,8 +464,6 @@ module ActiveSupport #:nodoc:
raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
end
- raise NameError, "#{from_mod} is not missing constant #{const_name}!" if from_mod.const_defined?(const_name, false)
-
qualified_name = qualified_name_for from_mod, const_name
path_suffix = qualified_name.underscore