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/ -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
On Tue, Nov 6, 2012 at 12:37 PM, Aaron Patterson <tenderlove@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. Not sure about changing that behavior. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
On Tue, Nov 06, 2012 at 01:36:53PM +0100, Xavier Noria wrote:> On Tue, Nov 6, 2012 at 12:37 PM, Aaron Patterson > <tenderlove@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.> 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. :''( -- Aaron Patterson http://tenderlovemaking.com/ -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.