# Sharing variables between classes and instances

**URL:** <https://www.ruby-forum.com/t/sharing-variables-between-classes-and-instances/137264>\
**Category:** Ruby\
**Created:** [May 11, 2008, 2:19am UTC](https://www.ruby-forum.com/t/sharing-variables-between-classes-and-instances/137264 "2008-05-11T02:19:46Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![leonb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/22d042/32.png) [@leonb](https://www.ruby-forum.com/u/leonb)\
**Post date:** [May 11, 2008, 2:19am UTC](https://www.ruby-forum.com/t/sharing-variables-between-classes-and-instances/137264/1 "2008-05-11T02:19:46Z")

</div>

Hi all,

What I’m trying to achieve: add a variable to a class. Fill it with  
data. Every nstance of that class should have access to the data in that  
variable. But I want every instance be able to modify that variable,  
without modifying the original value of the variable.

It’s like adding methods to the singleton class of an instance (if I  
explain it properly).

I think it becomes a lot clearer if you see the code I’ve written:  
[http://pastie.caboo.se/194982](http://pastie.caboo.se/194982)

I thought this guy described what I needed:  
[http://briancarper.net/2007/03/22/ruby-singleton-classes/](http://briancarper.net/2007/03/22/ruby-singleton-classes/)  
But even then I can’t get it to work.

Thanks in advance!  
Leon

---

<div class="post-metadata">

**Author:** ![leonb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/22d042/32.png) [@leonb](https://www.ruby-forum.com/u/leonb)\
**Post date:** [May 11, 2008, 2:41am UTC](https://www.ruby-forum.com/t/sharing-variables-between-classes-and-instances/137264/2 "2008-05-11T02:41:27Z")

</div>

Hi –

On Sun, 11 May 2008, Leon B. wrote:

> Hi all,
> 
> What I’m trying to achieve: add a variable to a class. Fill it with  
> data. Every nstance of that class should have access to the data in that  
> variable. But I want every instance be able to modify that variable,  
> without modifying the original value of the variable.

I’m not sure what you mean exactly. Do you mean each instance should  
have a copy of the object? If so, I would just do:

class Tester

def self.vars  
@vars ||= []  
end

def self.add\_var(var)  
self.vars \<\< var  
end

def vars  
@vars || self.class.vars  
end

def add\_var(var)  
@vars ||= self.class.vars.dup  
vars \<\< var  
end  
end

That gives the results you expect in your test.

David

---

<div class="post-metadata">

**Author:** ![leonb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/22d042/32.png) [@leonb](https://www.ruby-forum.com/u/leonb)\
**Post date:** [May 11, 2008, 2:33pm UTC](https://www.ruby-forum.com/t/sharing-variables-between-classes-and-instances/137264/3 "2008-05-11T14:33:55Z")

</div>

David A. Black wrote:

> Hi –
> 
> On Sun, 11 May 2008, Leon B. wrote:
> 
> > Hi all,
> > 
> > What I’m trying to achieve: add a variable to a class. Fill it with  
> > data. Every nstance of that class should have access to the data in that  
> > variable. But I want every instance be able to modify that variable,  
> > without modifying the original value of the variable.
> 
> I’m not sure what you mean exactly. Do you mean each instance should  
> have a copy of the object? If so, I would just do:
> 
> class Tester
> 
> def self.vars  
> @vars ||= []  
> end
> 
> def self.add\_var(var)  
> self.vars \<\< var  
> end
> 
> def vars  
> @vars || self.class.vars  
> end
> 
> def add\_var(var)  
> @vars ||= self.class.vars.dup  
> vars \<\< var  
> end  
> end
> 
> That gives the results you expect in your test.
> 
> David

Thanks David. That’s a whole lot simpler. I think I’ll stick with your  
example.  
Except I think I’ll merge @vars & self.class.vars each time vars() gets  
called. So you can update the original Tester class with new vars and  
that the instances have access to these new vars too.

Thanks!

---

<div class="post-metadata">

**Author:** ![leonb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/22d042/32.png) [@leonb](https://www.ruby-forum.com/u/leonb)\
**Post date:** [May 11, 2008, 4:09pm UTC](https://www.ruby-forum.com/t/sharing-variables-between-classes-and-instances/137264/4 "2008-05-11T16:09:51Z")

</div>

btw, you can simply do @@var to have a var that is shared among objects  
of the same class.

---

<div class="post-metadata">

**Author:** ![leonb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/22d042/32.png) [@leonb](https://www.ruby-forum.com/u/leonb)\
**Post date:** [May 11, 2008, 5:02pm UTC](https://www.ruby-forum.com/t/sharing-variables-between-classes-and-instances/137264/5 "2008-05-11T17:02:38Z")

</div>

On Sun, May 11, 2008 at 8:33 AM, Leon B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> David A. Black wrote:
> 
> > On Sun, 11 May 2008, Leon B. wrote:

> > > What I’m trying to achieve: add a variable to a class. Fill it with  
> > > data. Every nstance of that class should have access to the data in that  
> > > variable. But I want every instance be able to modify that variable,  
> > > without modifying the original value of the variable.

> > ```
> > self.vars << var
> > 
> > ```
> > 
> > end
> > 
> > That gives the results you expect in your test.

> Thanks David. That’s a whole lot simpler. I think I’ll stick with your  
> example.  
> Except I think I’ll merge @vars & self.class.vars each time vars() gets  
> called. So you can update the original Tester class with new vars and  
> that the instances have access to these new vars too.

You might also want to have a look at the class\_inheritable\_accessor  
and related methods from the activesupport gem (part of Rails), which  
never seems to come up in similar threads on Ruby talk. It sort of  
does what you want, although it sets things up when a class is  
subclassed and doesn’t keep up with changes.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![leonb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/22d042/32.png) [@leonb](https://www.ruby-forum.com/u/leonb)\
**Post date:** [May 11, 2008, 5:05pm UTC](https://www.ruby-forum.com/t/sharing-variables-between-classes-and-instances/137264/6 "2008-05-11T17:05:34Z")

</div>

On Sun, May 11, 2008 at 10:09 AM, Albert S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> btw, you can simply do @@var to have a var that is shared among objects  
> of the same class.

There be dragons! Class variables (@@var) in Ruby are also shared by  
subclasses (with some quirks in some cases such as when a superclass  
acquires a class variable AFTER one or more of its subclasses) and  
violate the expectations of almost everyone who tries to use them.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![leonb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/22d042/32.png) [@leonb](https://www.ruby-forum.com/u/leonb)\
**Post date:** [May 11, 2008, 7:50pm UTC](https://www.ruby-forum.com/t/sharing-variables-between-classes-and-instances/137264/7 "2008-05-11T19:50:43Z")

</div>

On May 10, 2008, at 6:40 PM, David A. Black wrote:

> have a copy of the object? If so, I would just do:
> 
> That gives the results you expect in your test.

careful, any ruby code that uses ‘dup’ or clone has serious bugs 9 out  
of 10 times, in the case it doesn’t meet the OP’s _requirements_  
(although the simple test case passes) at all:

cfp:~ \> cat a.rb

# 

# doesn’t let instance modify the var without modifying the class var

# 

Tester.add\_var ‘oops’  
t = Tester.new  
t.vars.first \<\< ‘, this modifies the original’  
p Tester.vars #=\> “oops, this modifies the original”

# 

# and doesn’t take a copy either

# 

Tester.vars.clear  
Tester.add\_var [‘oops’]  
t = Tester.new  
t.vars.first \<\< ‘, this modifies the original’  
p Tester.vars #=\> [[“oops”, “, this modifies the original”]]

BEGIN {  
class Tester  
def self.vars  
@vars ||= []  
end

```
def self.add_var(var)
  self.vars << var
end

def vars
  @vars || self.class.vars
end

def add_var(var)
  @vars ||= self.class.vars.dup
  vars << var
end

```

end  
}

cfp:~ \> ruby a.rb  
[“oops, this modifies the original”]  
[[“oops”, “, this modifies the original”]]

you really need one of two things: a factory or a smarter copy  
algorithm:

using a factory:

cfp:~ \> cat a.rb

class Shares  
Factory = lambda { |var|  
case var.to\_s  
when ‘a’  
‘not shared’  
when ‘b’  
‘but created fresh for class and instance cases’  
else  
end  
}

def Shares.a  
@a ||= Factory[‘a’]  
end

def a  
@a ||= Factory[‘a’]  
end  
end

p Shares.a

shares = Shares.new  
shares.a \<\< “, but it’s own copy”

p Shares.a  
p shares.a

cfp:~ \> ruby a.rb  
“not shared”  
“not shared”  
“not shared, but it’s own copy”

or, using a smart copy method:

cfp:~ \> cat a.rb  
class Shares  
def Shares.a  
@a ||= ‘not shared’  
end

def a  
@a ||= Marshal.load(Marshal.dump(Shares.a))  
end  
end

p Shares.a

shares = Shares.new  
shares.a \<\< “, but it’s own copy”

p Shares.a  
p shares.a

cfp:~ \> ruby a.rb  
“not shared”  
“not shared”  
“not shared, but it’s own copy”

this is nicer, but only works for objects you can marshal - obvisouly.

a @ [http://codeforpeople.com/](http://codeforpeople.com/)
