# The subtleties of const\_missing

**URL:** <https://www.ruby-forum.com/t/the-subtleties-of-const-missing/48042>\
**Category:** Ruby\
**Created:** [November 16, 2005, 5:39am UTC](https://www.ruby-forum.com/t/the-subtleties-of-const-missing/48042 "2005-11-16T05:39:41Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![nseckar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/e480ec/32.png) [@nseckar](https://www.ruby-forum.com/u/nseckar)\
**Post date:** [November 16, 2005, 5:39am UTC](https://www.ruby-forum.com/t/the-subtleties-of-const-missing/48042/1 "2005-11-16T05:39:41Z")

</div>

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” ?

Thanks for your time and any replies,  
Regards,  
Nicholas S.

---

<div class="post-metadata">

**Author:** ![nseckar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/e480ec/32.png) [@nseckar](https://www.ruby-forum.com/u/nseckar)\
**Post date:** [November 16, 2005, 5:57am UTC](https://www.ruby-forum.com/t/the-subtleties-of-const-missing/48042/2 "2005-11-16T05:57:45Z")

</div>

On Wed, 16 Nov 2005, Nicholas S. wrote:

> NameError: uninitialized constant A::B  
> class MyClass  
> returned.  
> 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

---

<div class="post-metadata">

**Author:** ![nseckar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/e480ec/32.png) [@nseckar](https://www.ruby-forum.com/u/nseckar)\
**Post date:** [November 16, 2005, 6:03am UTC](https://www.ruby-forum.com/t/the-subtleties-of-const-missing/48042/3 "2005-11-16T06:03:46Z")

</div>

On 15-Nov-05, at 11:57 PM, Ara.T.Howard wrote:

> does your  
> handler do?

The loaded file is expected to define the constant; We assume b.rb  
contains class or module B (or defines it in any other way). If the  
constant isn’t defined by the loaded file then a NameError is raised  
as if normal.

---

<div class="post-metadata">

**Author:** ![nseckar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/e480ec/32.png) [@nseckar](https://www.ruby-forum.com/u/nseckar)\
**Post date:** [November 16, 2005, 6:30am UTC](https://www.ruby-forum.com/t/the-subtleties-of-const-missing/48042/4 "2005-11-16T06:30:58Z")

</div>

On Nov 15, 2005, at 8:36 PM, Nicholas S. wrote:

> 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:

I have found this type of laziness often leads to errors that are  
difficult to discover because somewhere else a MyModule was defined  
leaving the file I really want to use unrequired.

require ‘my\_module’ is really not that hard to type.

---

<div class="post-metadata">

**Author:** ![nseckar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/e480ec/32.png) [@nseckar](https://www.ruby-forum.com/u/nseckar)\
**Post date:** [November 16, 2005, 6:37am UTC](https://www.ruby-forum.com/t/the-subtleties-of-const-missing/48042/5 "2005-11-16T06:37:01Z")

</div>

Hi,

At Wed, 16 Nov 2005 13:36:46 +0900,  
Nicholas S. wrote in [ruby-talk:165996]:

> However it seems impossible to detect which case we are in within the  
> const\_missing method. A more detailed explanation follows:

What about autoload?

$ echo ‘B = 10’ \> b.rb

$ irb  
irb(main):001:0\> autoload :B, “b”  
=\> nil  
irb(main):002:0\> module A;end  
=\> nil  
irb(main):003:0\> A::B  
NameError: uninitialized constant A::B  
from (irb):3  
from :0  
irb(main):004:0\> module A;B;end  
=\> 10  
irb(main):005:0\> A::B  
NameError: uninitialized constant A::B  
from (irb):5  
from :0  
irb(main):006:0\>

---

<div class="post-metadata">

**Author:** ![nseckar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/e480ec/32.png) [@nseckar](https://www.ruby-forum.com/u/nseckar)\
**Post date:** [November 16, 2005, 11:38am UTC](https://www.ruby-forum.com/t/the-subtleties-of-const-missing/48042/6 "2005-11-16T11:38:49Z")

</div>

Nicholas S. wrote:

> 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:

I’m not sure what you’re up to. You define B in a completely different  
scope than you use for lookup. Maybe you can give a more real life  
example of what you are actually trying to do.

Kind regards

```
robert
```

---

<div class="post-metadata">

**Author:** ![nseckar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/e480ec/32.png) [@nseckar](https://www.ruby-forum.com/u/nseckar)\
**Post date:** [November 16, 2005, 2:48pm UTC](https://www.ruby-forum.com/t/the-subtleties-of-const-missing/48042/7 "2005-11-16T14:48:52Z")

</div>

On Wed, 16 Nov 2005, Nicholas S. wrote:

> The loaded file is expected to define the constant; We assume b.rb contains  
> class or module B (or defines it in any other way). If the constant isn’t  
> defined by the loaded file then a NameError is raised as if normal.

i understand that. but in your original message you said

> 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.

here you will see that wether we reference B from inside M, or as M::B  
the  
handler is called exactly once.

harp:~ \> cat a.rb  
class Module  
def const\_missing c  
puts “const\_missing called once…”  
const\_set c, 42  
end  
end

module A  
p B  
end

p A::B

harp:~ \> ruby a.rb  
const\_missing called once…  
42  
42

here is another example which loads a file

harp:~ \> cat a.rb  
class Module  
def const\_missing c  
puts “const\_missing called once…”  
autoload = {  
:B =\> ‘b.rb’  
}  
autoload[c] ? require(autoload[c]) : super  
const\_set(c, const\_get©)  
end  
end

module A  
B  
end

A::B

module A; p B; end  
p A::B

harp:~ \> ruby a.rb  
const\_missing called once…  
42  
42

so what **exactly** are you trying to do in your handler that does not  
work? i  
understand you problem but, as the second example shows, it can easily  
be  
solved without distinguishing the two syntax cases because, afaikt, ruby  
handles them precisely the same.

hth.

-a

---

<div class="post-metadata">

**Author:** ![nseckar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/e480ec/32.png) [@nseckar](https://www.ruby-forum.com/u/nseckar)\
**Post date:** [November 16, 2005, 3:44pm UTC](https://www.ruby-forum.com/t/the-subtleties-of-const-missing/48042/8 "2005-11-16T15:44:17Z")

</div>

Hi,

Rails does this very thing. You should check out their const\_missing and  
see if it suffers from the self-same problem.

Devin
