From: "Ara.T.Howard" Date: 2005-11-16T13:57:12+09:00 Subject: Re: The subtleties of const_missing On Wed, 16 Nov 2005, Nicholas Seckar wrote: > Hello all, > > I've run into an issue regarding the use of const_missing. This issue > revolves around the fact that these two cases are supposed to behave > differently from each other: > > irb(main):001:0> B = 10 > irb(main):002:0> module A; B; end > => 10 > irb(main):003:0> A::B > NameError: uninitialized constant A::B > from (irb):3 > > However it seems impossible to detect which case we are in within the > const_missing method. A more detailed explanation follows: > > Suppose we are lazy and avoid typing "require 'my_module.rb'" by defining a > const_missing that performs that require when MyModule is first referenced. > Now, suppose we are writing my_class, and wish to include MyModule. So, we > put this code in my_class.rb: > > class MyClass > include MyModule > ... > end > > Our const_missing handler is called, and it loads 'my_module.rb', finds the > now present MyModule constant, and returns it. Everything is good. > > However, let's say we're slightly misguided and do MyClass::MyModule. Since > this is not defined, our const_missing handler is once again called. > 'my_module.rb' is thus loaded again, (usually to no effect,) and MyModule > returned. > > This is a pretty clear violation of the semantics of ::. Indeed, Ruby will > produce a warning regarding our misbehaved const_missing. That said, there > does not seem to be a way to behave correctly; from inside the const_missing > handler there is no way to tell which case the constant is missing in. > > One way to 'fix' this is to have our const_missing look in it's parent > modules for the missing constant. If we find it there, we know this is a > case of A::B. However this only works if the missing constant has been > defined in one of the parents. Thus, we can still load ::B using A::B, but > afterwards A::B will fail. > > So, sorry for rambling on. The real question is: Can const_missing detect if > we are in a "A::B" case rather than "module A; B; end" ? but why do you need to distinguish? harp:~ > cat a.rb class Module def const_missing c puts "const_missing..." const_set c, 42 end end module A p B end p A::B harp:~ > ruby a.rb const_missing... 42 42 the 'const_missing' hook will continue to get call only so long as it remain undefined - if your handler merely loads a file but does not actually define any const then of course it will continue to fire. what, exactly, does your handler do? kind regards. -a -- =============================================================================== | ara [dot] t [dot] howard [at] gmail [dot] com | all happiness comes from the desire for others to be happy. all misery | comes from the desire for oneself to be happy. | -- bodhicaryavatara ===============================================================================