# Constants and metaclasses

**URL:** <https://rubytalk.org/t/constants-and-metaclasses/38268>\
**Category:** ruby-talk\
**Created:** [11 June 2007 18:19 UTC](https://rubytalk.org/t/constants-and-metaclasses/38268 "2007-06-11T18:19:24Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andreas\_Launila](https://avatars.discourse-cdn.com/v4/letter/a/dbc845/32.png) [@Andreas\_Launila](https://rubytalk.org/u/Andreas_Launila)\
**Post date:** [11 June 2007 18:19 UTC](https://rubytalk.org/t/constants-and-metaclasses/38268/1 "2007-06-11T18:19:24Z")

</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  
&nbsp;&nbsp;def foo  
&nbsp;&nbsp;&nbsp;&nbsp;p BAR  
&nbsp;&nbsp;end  
end

f = Foo.new  
class \<\<f  
&nbsp;&nbsp;BAR = "Hello"

&nbsp;&nbsp;def bar  
&nbsp;&nbsp;&nbsp;&nbsp;p BAR  
&nbsp;&nbsp;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")?

> **···**
>
> --  
> Andreas Launila

---

<div class="post-metadata">

**Author:** ![Joel\_VanderWerf1](https://avatars.discourse-cdn.com/v4/letter/j/94ad74/32.png) [@Joel\_VanderWerf1](https://rubytalk.org/u/Joel_VanderWerf1)\
**Post date:** [11 June 2007 18:37 UTC](https://rubytalk.org/t/constants-and-metaclasses/38268/2 "2007-06-11T18:37:30Z")

</div>

Andreas Launila wrote:

> 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  
> &nbsp;&nbsp;def foo  
> &nbsp;&nbsp;&nbsp;&nbsp;p BAR  
> &nbsp;&nbsp;end  
> end
> 
> f = Foo.new  
> class \<\<f  
> &nbsp;&nbsp;BAR = "Hello"
> 
> &nbsp;&nbsp;def bar  
> &nbsp;&nbsp;&nbsp;&nbsp;p BAR  
> &nbsp;&nbsp;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")?

Yes, with a little wrangling:

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

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

f = Foo.new  
class \<\<f  
&nbsp;&nbsp;&nbsp;BAR = "Hello"

&nbsp;&nbsp;&nbsp;def bar  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p BAR  
&nbsp;&nbsp;&nbsp;end  
end

f.bar  
f.foo

> **···**
>
> --  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [11 June 2007 19:38 UTC](https://rubytalk.org/t/constants-and-metaclasses/38268/3 "2007-06-11T19:38:49Z")

</div>

Hi --

> **···**
>
> On Tue, 12 Jun 2007, Andreas Launila wrote:
> 
> > 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  
> > &nbsp;&nbsp;&nbsp;p BAR  
> > end  
> > end
> > 
> > f = Foo.new  
> > class \<\<f  
> > BAR = "Hello"
> > 
> > def bar  
> > &nbsp;&nbsp;&nbsp;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")?
> 
> 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:
> 
> &nbsp;&nbsp;&nbsp;class \<\< f  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Foo::BAR = "Hello"
> 
> etc.
> 
> David
> 
> --  
> \* Books:  
> &nbsp;&nbsp;&nbsp;RAILS ROUTING (new! [http://safari.awprofessional.com/9780321509246\](http://safari.awprofessional.com/9780321509246%5C))  
> &nbsp;&nbsp;&nbsp;RUBY FOR RAILS ([http://www.manning.com/black\](http://www.manning.com/black%5C))  
> \* Ruby/Rails training  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;& consulting: Ruby Power and Light, LLC ([http://www.rubypal.com](http://www.rubypal.com))

---

<div class="post-metadata">

**Author:** ![Andreas\_Launila](https://avatars.discourse-cdn.com/v4/letter/a/dbc845/32.png) [@Andreas\_Launila](https://rubytalk.org/u/Andreas_Launila)\
**Post date:** [11 June 2007 19:15 UTC](https://rubytalk.org/t/constants-and-metaclasses/38268/4 "2007-06-11T19:15:39Z")

</div>

Joel VanderWerf wrote:

> Andreas Launila wrote:
> 
> > 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  
> &nbsp;&nbsp;def singleton\_class  
> &nbsp;&nbsp;&nbsp;&nbsp;class \<\< self; self; end  
> &nbsp;&nbsp;end  
> end
> 
> class Foo  
> &nbsp;&nbsp;def foo  
> &nbsp;&nbsp;&nbsp;&nbsp;p self.singleton\_class::BAR  
> &nbsp;&nbsp;end  
> end

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.

> **···**
>
> --  
> Andreas Launila

---

<div class="post-metadata">

**Author:** ![Joel\_VanderWerf1](https://avatars.discourse-cdn.com/v4/letter/j/94ad74/32.png) [@Joel\_VanderWerf1](https://rubytalk.org/u/Joel_VanderWerf1)\
**Post date:** [11 June 2007 19:47 UTC](https://rubytalk.org/t/constants-and-metaclasses/38268/5 "2007-06-11T19:47:51Z")

</div>

Andreas Launila wrote:

> Joel VanderWerf wrote:
> 
> > Andreas Launila wrote:
> > 
> > > 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  
> > &nbsp;&nbsp;def singleton\_class  
> > &nbsp;&nbsp;&nbsp;&nbsp;class \<\< self; self; end  
> > &nbsp;&nbsp;end  
> > end
> > 
> > class Foo  
> > &nbsp;&nbsp;def foo  
> > &nbsp;&nbsp;&nbsp;&nbsp;p self.singleton\_class::BAR  
> > &nbsp;&nbsp;end  
> > end
> 
> 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.

> **···**
>
> --  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

---

<div class="post-metadata">

**Author:** ![Andreas\_Launila](https://avatars.discourse-cdn.com/v4/letter/a/dbc845/32.png) [@Andreas\_Launila](https://rubytalk.org/u/Andreas_Launila)\
**Post date:** [11 June 2007 21:01 UTC](https://rubytalk.org/t/constants-and-metaclasses/38268/6 "2007-06-11T21:01:26Z")

</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  
&nbsp;&nbsp;def singleton\_class  
&nbsp;&nbsp;&nbsp;&nbsp;class \<\< self; self; end  
&nbsp;&nbsp;end  
end

class Foo  
&nbsp;&nbsp;def foo  
&nbsp;&nbsp;&nbsp;&nbsp;p BAR  
&nbsp;&nbsp;end

&nbsp;&nbsp;private

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

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

f = Foo.new  
class \<\<f  
&nbsp;&nbsp;BAR = "Hello"

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

g = Foo.new  
class \<\<g  
&nbsp;&nbsp;BAR = "Goodbye"

&nbsp;&nbsp;alias\_method :old\_foo, :foo  
&nbsp;&nbsp;def foo  
&nbsp;&nbsp;&nbsp;&nbsp;self.class.next\_caller(self)  
&nbsp;&nbsp;&nbsp;&nbsp;old\_foo  
&nbsp;&nbsp;&nbsp;&nbsp;self.class.next\_caller(nil)  
&nbsp;&nbsp;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 🙂

> **···**
>
> --  
> Andreas Launila
