# Constants and metaclasses

**URL:** <https://www.ruby-forum.com/t/constants-and-metaclasses/106543>\
**Category:** Ruby\
**Created:** [June 11, 2007, 8:21pm UTC](https://www.ruby-forum.com/t/constants-and-metaclasses/106543 "2007-06-11T20:21:07Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![andreas\_l](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/7bcc69/32.png) [@andreas\_l](https://www.ruby-forum.com/u/andreas_l)\
**Post date:** [June 11, 2007, 8:21pm UTC](https://www.ruby-forum.com/t/constants-and-metaclasses/106543/1 "2007-06-11T20:21:07Z")

</div>

Is there a way to define a constant in a metaclass and then have it used  
in methods defined in the original class?

An example:

class Foo  
def foo  
p BAR  
end  
end

f = Foo.new  
class \<\<f  
BAR = “Hello”

def bar  
p BAR  
end  
end

f.bar  
f.foo

The line “f.bar” will work fine, but “f.foo” will fail with “NameError:  
uninitialized constant Foo::BAR”. Is there some way to have the method  
defined in the original class pick up on the constant in the metaclass  
(without altering “p BAR”)?

---

<div class="post-metadata">

**Author:** ![andreas\_l](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/7bcc69/32.png) [@andreas\_l](https://www.ruby-forum.com/u/andreas_l)\
**Post date:** [June 11, 2007, 8:38pm UTC](https://www.ruby-forum.com/t/constants-and-metaclasses/106543/2 "2007-06-11T20:38:10Z")

</div>

Andreas L. wrote:

> end  
> f.bar  
> f.foo
> 
> The line “f.bar” will work fine, but “f.foo” will fail with “NameError:  
> uninitialized constant Foo::BAR”. Is there some way to have the method  
> defined in the original class pick up on the constant in the metaclass  
> (without altering “p BAR”)?

Yes, with a little wrangling:

class Object  
def singleton\_class  
class \<\< self; self; end  
end  
end

class Foo  
def foo  
p self.singleton\_class::BAR  
end  
end

f = Foo.new  
class \<\<f  
BAR = “Hello”

def bar  
p BAR  
end  
end

f.bar  
f.foo

---

<div class="post-metadata">

**Author:** ![andreas\_l](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/7bcc69/32.png) [@andreas\_l](https://www.ruby-forum.com/u/andreas_l)\
**Post date:** [June 11, 2007, 9:16pm UTC](https://www.ruby-forum.com/t/constants-and-metaclasses/106543/3 "2007-06-11T21:16:22Z")

</div>

Joel VanderWerf wrote:

> def singleton\_class

Yes that works, but I’m specifically looking for something that does not  
alter the line “p BAR”. To get around that one would have to dynamically  
set the constant BAR in the main class before executing “p BAR”. A  
problem with that comes when one has multiple instances and metaclasses,  
one would end up changing the value of a constant each time the method  
is invoked. Thanks for the reply though.

---

<div class="post-metadata">

**Author:** ![andreas\_l](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/7bcc69/32.png) [@andreas\_l](https://www.ruby-forum.com/u/andreas_l)\
**Post date:** [June 11, 2007, 9:40pm UTC](https://www.ruby-forum.com/t/constants-and-metaclasses/106543/4 "2007-06-11T21:40:29Z")

</div>

Hi –

On Tue, 12 Jun 2007, Andreas L. wrote:

> end  
> f.bar  
> f.foo
> 
> The line “f.bar” will work fine, but “f.foo” will fail with “NameError:  
> uninitialized constant Foo::BAR”. Is there some way to have the method  
> defined in the original class pick up on the constant in the metaclass  
> (without altering “p BAR”)?

I don’t think so (and I hope not, as it would be kind of strange 🙂  
but you could define BAR in the original class:

class \<\< f  
Foo::BAR = “Hello”

etc.

David

---

<div class="post-metadata">

**Author:** ![andreas\_l](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/7bcc69/32.png) [@andreas\_l](https://www.ruby-forum.com/u/andreas_l)\
**Post date:** [June 11, 2007, 9:49pm UTC](https://www.ruby-forum.com/t/constants-and-metaclasses/106543/5 "2007-06-11T21:49:30Z")

</div>

Andreas L. wrote:

> > def singleton\_class
> 
> Yes that works, but I’m specifically looking for something that does not  
> alter the line “p BAR”. To get around that one would have to dynamically  
> set the constant BAR in the main class before executing “p BAR”. A  
> problem with that comes when one has multiple instances and metaclasses,  
> one would end up changing the value of a constant each time the method  
> is invoked. Thanks for the reply though.

Oops, sorry.

It doesn’t seem possible to use const\_missing to do this, because  
const\_missing is called on Foo (not on the instance or the singleton  
class) and there is no way to identify the instance of Foo in the  
const\_missing method.

---

<div class="post-metadata">

**Author:** ![andreas\_l](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/7bcc69/32.png) [@andreas\_l](https://www.ruby-forum.com/u/andreas_l)\
**Post date:** [June 11, 2007, 11:02pm UTC](https://www.ruby-forum.com/t/constants-and-metaclasses/106543/6 "2007-06-11T23:02:49Z")

</div>

Joel VanderWerf wrote:

> It doesn’t seem possible to use const\_missing to do this, because  
> const\_missing is called on Foo (not on the instance or the singleton  
> class) and there is no way to identify the instance of Foo in the  
> const\_missing method.

I didn’t know that const\_missing existed, that might be just enough to  
not have to redefine constants if one accepts some dirtiness. Here is an  
adaptation of your code with that thrown in.

class Object  
def singleton\_class  
class \<\< self; self; end  
end  
end

class Foo  
def foo  
p BAR  
end

private

def self.const\_missing(name)  
if !@caller.nil? and @caller.singleton\_class.const\_defined? name  
@caller.singleton\_class.const\_get(name)  
else  
super  
end  
end

def self.next\_caller(caller)  
@caller = caller  
end  
end

f = Foo.new  
class \<\<f  
BAR = “Hello”

alias\_method :old\_foo, :foo  
def foo  
self.class.next\_caller(self)  
old\_foo  
self.class.next\_caller(nil)  
end  
end

g = Foo.new  
class \<\<g  
BAR = “Goodbye”

alias\_method :old\_foo, :foo  
def foo  
self.class.next\_caller(self)  
old\_foo  
self.class.next\_caller(nil)  
end  
end

f.foo  
g.foo  
f.foo

Outputs  
“Hello”  
“Goodbye”  
“Hello”

It isn’t pretty, it isn’t thread safe, it will not work if Foo is called  
directly, it could be shortened/generalized/altered/improved depending  
on the purpose.

Thank you 🙂
