Inconsistency in "constantize"

122 views
Skip to first unread message

Aaron Patterson

unread,
Nov 6, 2012, 6:37:37 AM11/6/12
to rubyonra...@googlegroups.com
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?

--
Aaron Patterson
http://tenderlovemaking.com/

Xavier Noria

unread,
Nov 6, 2012, 7:36:53 AM11/6/12
to rubyonrails-core
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.

Not sure about changing that behavior.

Aaron Patterson

unread,
Nov 6, 2012, 6:51:34 PM11/6/12
to rubyonra...@googlegroups.com
That is correct. This implementation const_get would find class.

> Not sure about changing that behavior.

Neither am I, that's why I emailed. ;-)

It's a shame, I'm not actually sure what the new `const_get` buys us if
we can't replace this method. :'(
Reply all
Reply to author
Forward
0 new messages