I noticed the following today I''ve a module SecuritySystem::SecretsProxy. SecuritySystem::SecretsProxy::AnyConstant evaluates to AnyConstant (as long as AnyConstant is something Dependencies can load but is not loaded yet), even though AnyConstant isn''t defined at that level. The second time you evaluate SecuritySystem::SecretsProxy::AnyConstant then you get a NameError as I expected to get in the first place. When load_missing_constant is called (to find AnyConstant inside SecuritySystem::SecretsProxy) it does check whether any of its parents defined AnyConstant (precisely so that SecuritySystem::SecretsProxy::AnyConstant cannot find ::AnyConstant. However in the edge case I describe AnyConstant has not been loaded at all and so this check does nothing. I think this is slightly unhelpful behaviour (I certainly spent some time scratching my head as a result of it, the fact that it didn''t occur in development because of the the reloading that goes on made it even more interesting). I''ve done a little playing around to see if I could catch this and raise a more helpful NameError but can''t (at least not after half an hour''s fiddling) come up with something that correctly identifies this situation. Am I flogging a dead horse or does anyone have a bright idea/ helpful insight into this? Fred --~--~---------~--~----~------------~-------~--~----~ 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 Apr 9, 2008, at 22:04 , Frederick Cheung wrote:> I''ve a module SecuritySystem::SecretsProxy. > SecuritySystem::SecretsProxy::AnyConstant evaluates to AnyConstant (as > long as AnyConstant is something Dependencies can load but is not > loaded yet), even though AnyConstant isn''t defined at that level. The > second time you evaluate SecuritySystem::SecretsProxy::AnyConstant > then you get a NameError as I expected to get in the first place.From the description I am not sure I understand the setup. Frederick would you please send a minimal example to be able to reproduce it? -- fxn --~--~---------~--~----~------------~-------~--~----~ 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 9 Apr 2008, at 22:16, Xavier Noria wrote:> > On Apr 9, 2008, at 22:04 , Frederick Cheung wrote: > >> I''ve a module SecuritySystem::SecretsProxy. >> SecuritySystem::SecretsProxy::AnyConstant evaluates to AnyConstant >> (as >> long as AnyConstant is something Dependencies can load but is not >> loaded yet), even though AnyConstant isn''t defined at that level. The >> second time you evaluate SecuritySystem::SecretsProxy::AnyConstant >> then you get a NameError as I expected to get in the first place. > > From the description I am not sure I understand the setup. Frederick > would you please send a minimal example to be able to reproduce it?Sure. From an empty rails app (or not), create in lib/any_constant.rb: class AnyConstant end in lib/my_lib/my_module.rb module MyLib module MyModule end end Now from script/console: >> MyLib::MyModule::AnyConstant => AnyConstant but try it a second time >> MyLib::MyModule::AnyConstant NameError: uninitialized constant MyLib::MyModule::AnyConstant from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/ active_support/dependencies.rb:266:in `load_missing_constant'' from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/ active_support/dependencies.rb:453:in `const_missing'' from (irb):3 Fred --~--~---------~--~----~------------~-------~--~----~ 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 Apr 10, 2008, at 10:32 , Frederick Cheung wrote:> On 9 Apr 2008, at 22:16, Xavier Noria wrote: > >> >> On Apr 9, 2008, at 22:04 , Frederick Cheung wrote: >> >>> I''ve a module SecuritySystem::SecretsProxy. >>> SecuritySystem::SecretsProxy::AnyConstant evaluates to AnyConstant >>> (as >>> long as AnyConstant is something Dependencies can load but is not >>> loaded yet), even though AnyConstant isn''t defined at that level. >>> The >>> second time you evaluate SecuritySystem::SecretsProxy::AnyConstant >>> then you get a NameError as I expected to get in the first place. >> >> From the description I am not sure I understand the setup. Frederick >> would you please send a minimal example to be able to reproduce it? > > > Sure. From an empty rails app (or not), create in > lib/any_constant.rb: > class AnyConstant > end > in lib/my_lib/my_module.rb > module MyLib > module MyModule > end > end > > Now from script/console: > >>> MyLib::MyModule::AnyConstant > => AnyConstant > but try it a second time >>> MyLib::MyModule::AnyConstant > NameError: uninitialized constant MyLib::MyModule::AnyConstant > from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/ > active_support/dependencies.rb:266:in `load_missing_constant'' > from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/ > active_support/dependencies.rb:453:in `const_missing'' > from (irb):3 >Thank you! This smells like a bug to me. From what I remember the intention of the implementation of dependencies.rb is to create intermediate modules as needed, and dynamically put the constants where they belong. So (talking from memory) I''d expect the first const_missing to fail. I''ll have a llok at it it. -- fxn --~--~---------~--~----~------------~-------~--~----~ 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 Apr 9, 2008, at 22:04 , Frederick Cheung wrote:> I''ve a module SecuritySystem::SecretsProxy. > SecuritySystem::SecretsProxy::AnyConstant evaluates to AnyConstant (as > long as AnyConstant is something Dependencies can load but is not > loaded yet), even though AnyConstant isn''t defined at that level. The > second time you evaluate SecuritySystem::SecretsProxy::AnyConstant > then you get a NameError as I expected to get in the first place. > > When load_missing_constant is called (to find AnyConstant inside > SecuritySystem::SecretsProxy) it does check whether any of its parents > defined AnyConstant (precisely so that > SecuritySystem::SecretsProxy::AnyConstant cannot find ::AnyConstant. > However in the edge case I describe AnyConstant has not been loaded at > all and so this check does nothing. > > I think this is slightly unhelpful behaviour (I certainly spent some > time scratching my head as a result of it, the fact that it didn''t > occur in development because of the the reloading that goes on made it > even more interesting). I''ve done a little playing around to see if I > could catch this and raise a more helpful NameError but can''t (at > least not after half an hour''s fiddling) come up with something that > correctly identifies this situation.const_missing calls one way or another someting like Dependencies.load_missing_constant(self, const_name) which is the single entry point to dependencies.rb. I think the key point is that the current approach to autoloading cannot distinguish module M CONSTANT_TO_AUTOLOAD end from M::CONSTANT_TO_AUTOLOAD The second use case is less flexible than the first one because there''s no doubt that if there''s any CONSTANT_TO_AUTOLOAD to look for it should be defined in some m/constant_to_autoload.rb. It should be a constant named "CONSTANT_TO_AUTOLOAD" that would belong to some module with at least basename "M". That can''t end falling back to ::CONSTANT_TO_AUTOLOAD. But as you noticed that''s what it does in the second use case. For example, given app/models/admin lib/user.rb a few added traces show that dependencies.rb looks for Admin::User this way: $ script/runner ''puts Admin::User'' 1) Class#const_missing for Object::Admin 2) Module#const_missing for Object::Admin 3) Module#const_missing for Admin::User 4) Class#const_missing for Object::User 5) Module#const_missing for Object::User 6) User The Admin module is defined on-the-fly after 2). 3) fails resolving admin/user.rb because it does not exist. And then instead of halting it still finds user.rb and define User in Object. In my opinion this behaviour is wrong. But it would be right if we had written instead $ script/runner ''module Admin; User; end'' because you are here kind of emulating the lexical side of constant name resolution. The bad news are that from within dependencies.rb I see no way at 1:34 AM to distinguish both use cases. As a quick thought I believe you''d need to be able to know what''s Module.nesting in the caller. Hmmm. -- fxn --~--~---------~--~----~------------~-------~--~----~ 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 Apr 13, 2008, at 1:35 , Xavier Noria wrote:> M::CONSTANT_TO_AUTOLOAD > > The second use case is less flexible than the first one because > there''s no doubt that if there''s any CONSTANT_TO_AUTOLOAD to look > for it should be defined in some m/constant_to_autoload.rb. It > should be a constant named "CONSTANT_TO_AUTOLOAD" that would belong > to some module with at least basename "M".Just for the archives: I forgot a "conventionally" there or something like that. Technically the basename of the class or module under the M in M::CONSTANT_TO_AUTOLOAD may not be "M". For example this way: module X; end M = X M::CONSTANT_TO_AUTOLOAD There the (base)name of the module under M is "X". -- fxn --~--~---------~--~----~------------~-------~--~----~ 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 13 Apr 2008, at 00:35, Xavier Noria wrote:> I think the key point is that the current approach to autoloading > cannot distinguish > > module M > CONSTANT_TO_AUTOLOAD > end > > from > > M::CONSTANT_TO_AUTOLOAD >Hi Xavier, Thanks for looking into this. I agree that this is the crux of the matter and couldn''t figure out anything either :-) Fred --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---