On Tue, Nov 06, 2012 at 01:36:53PM +0100, Xavier Noria wrote:
> On Tue, Nov 6, 2012 at 12:37 PM, Aaron Patterson
> <tenderl
...@ruby-lang.org> wrote:
> > Hi,
> > I've changed `const_get` in Ruby 2.0. If it were implemented in 1.9, it
> > would look roughly like this:
> > def const_get name, inherited = true
> > name.to_s.split('::').inject(self.class) do |klass, name|
> > klass.const_get name, inherited
> > end
> > end
> > I was hoping we could use this to replace the implementation of
> > `constantize`, but it seems we have an inconsistency in the way that
> > `constantize` works in regard to constant inheritance.
> > I've written a test to demonstrate the problem:
> > https://gist.github.com/4024158
> > For some reason `constantize` inherits constants, but not when the
> > constant is defined on Object, where `const_get` in Ruby 2.0 will always
> > honor the inheritance (even if the constant is defined at the top).
> > Is there any chance we can change this?
> Yeah, at first sight they seem to be different in their intention. The
> new const_get is implemented as a recursive const_get, whereas
> constantize is closer to emulate the resolution algorithm for constant
> paths.
> The subtle difference is in modules, as the test shows.
> As you know, X::String raises a NameError if X is a module, and
> resolves with a warning if X is a class that inherits from Object,
> because Object is among its ancestors but the access is considered
> dubious anyway. That's what constantize kinda emulates. I believe
> "constantize" also raises if X is a class, and always treats the first
> constant in the path as if it had a leading double colon "::", that's
> why I say "kinda".
> "Admin::UsersController".constantize fails if such controller does not
> exist, regardless of the existence of an eventual top-level
> UsersController, whereas if I understand it correctly
> Object.const_get("Admin::UsersController", true) would resolve to such
> top-level controller, because the original const_get name, inherit
> does check Object by hand for modules, as the algorithm for relative
> constant names does.
That is correct. This implementation const_get would find class.