# Setting instance variable "dynamically"

**URL:** <https://rubytalk.org/t/setting-instance-variable-dynamically/9732>\
**Category:** ruby-talk\
**Created:** [18 January 2004 17:29 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732 "2004-01-18T17:29:59Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Bauduin\_Raphael](https://avatars.discourse-cdn.com/v4/letter/b/b19c9b/32.png) [@Bauduin\_Raphael](https://rubytalk.org/u/Bauduin_Raphael)\
**Post date:** [18 January 2004 17:29 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732/1 "2004-01-18T17:29:59Z")

</div>

I saw in the pickaxe there’s a way to call methods dynamically, with  
send(“method\_name”):

“test”.send(“length”) # 4

What I want to do is set a variable this way. Is it possible?

I’m working on a translation tool for a website. rows returned  
are of the form:  
[“id”, “language”, “value”]

the value of the language field is the identical to the member variable  
that will contain the row (wrapped in an object actually).

I thought of something like this:

class Term  
attr :query, :fr, :nl, :en  
def initialize(dbh, id)  
@query = "select \* from translations where id=’#{id}’"  
dbh.select\_all(query) do |row|  
self.send(row[1].to\_s)=Translation.new(row)  
end  
end  
def get\_french()  
@fr.value  
end  
end

But that isn’t accepted.  
Does anyone have the solution?

Thanks

Raph

---

<div class="post-metadata">

**Author:** ![Martin\_Hart](https://avatars.discourse-cdn.com/v4/letter/m/54ee81/32.png) [@Martin\_Hart](https://rubytalk.org/u/Martin_Hart)\
**Post date:** [18 January 2004 17:40 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732/2 "2004-01-18T17:40:31Z")

</div>

class MyClass  
def initialize  
@name = “fred”  
end  
end

m = MyClass.new  
m.instance\_eval { @name = “freda” }

var = “name”  
m.instance\_eval(“@#{var} = ‘frederick’”)

the second is a bit messy - I’m sure there is an easier way 🙂

Cheers,  
Martin

> **···**
>
> On Sunday 18 January 2004 17:29, Bauduin Raphael wrote:
> 
> > I saw in the pickaxe there’s a way to call methods dynamically, with  
> > send(“method\_name”):
> > 
> > “test”.send(“length”) # 4
> > 
> > What I want to do is set a variable this way. Is it possible?

---

<div class="post-metadata">

**Author:** ![Mauricio\_Fernndez](https://avatars.discourse-cdn.com/v4/letter/m/e495f1/32.png) [@Mauricio\_Fernndez](https://rubytalk.org/u/Mauricio_Fernndez)\
**Post date:** [18 January 2004 17:53 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732/3 "2004-01-18T17:53:37Z")

</div>

> I saw in the pickaxe there’s a way to call methods dynamically, with  
> send(“method\_name”):
> 
> “test”.send(“length”) # 4
> 
> What I want to do is set a variable this way. Is it possible?

> > class A; end; a = A.new  
> > =\> #\<A:0x401ff0d8\>  
> > a.instance\_variable\_set :@foo, “foo”  
> > =\> “foo”  
> > a  
> > =\> #\<A:0x401ff0d8 @foo=“foo”\>  
> > a.instance\_variable\_get :@foo  
> > =\> “foo”

> **···**
>
> On Mon, Jan 19, 2004 at 02:29:59AM +0900, Bauduin Raphael wrote:
> 
> –  
> \_ \_
> 
> > > \_\_ \_\_ _| |_ \_\_\_ \_ \_\_ \_\_\_ \_\_ \_ \_ \_\_  
> > > '\_ \ / _`| __/__ | '_` \_ \ / ` | ’ \   
> > > ) | (| | |_\_\_ \ | | | | | (_| | | | |  
> > > .\_\_/ \_,_|\ __|__ /| |_| |_|\__,_|_| |\_|  
> > > Running Debian GNU/Linux Sid (unstable)  
> > > batsman dot geo at yahoo dot com
> 
> No, that’s wrong too. Now there’s a race condition between the rm and  
> the mv. Hmm, I need more coffee.  
> – Guy Maor on Debian Bug#25228

---

<div class="post-metadata">

**Author:** ![Laurent\_Julliard4](https://avatars.discourse-cdn.com/v4/letter/l/ebca7d/32.png) [@Laurent\_Julliard4](https://rubytalk.org/u/Laurent_Julliard4)\
**Post date:** [18 January 2004 23:15 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732/4 "2004-01-18T23:15:04Z")

</div>

> I saw in the pickaxe there’s a way to call methods dynamically, with  
> send(“method\_name”):
> 
> “test”.send(“length”) # 4
> 
> What I want to do is set a variable this way. Is it possible?
> 
> I’m working on a translation tool for a website. rows returned  
> are of the form:  
> [“id”, “language”, “value”]
> 
> the value of the language field is the identical to the member variable  
> that will contain the row (wrapped in an object actually).
> 
> I thought of something like this:
> 
> class Term  
> attr :query, :fr, :nl, :en  
> def initialize(dbh, id)  
> @query = “select \* from translations where id=‘#{id}’”  
> dbh.select\_all(query) do |row|  
> self.send(row[1].to\_s)=Translation.new(row)  
> end  
> end  
> def get\_french()  
> @fr.value  
> end  
> end
> 
> But that isn’t accepted.  
> Does anyone have the solution?

> > class C  
> > def initialize  
> > @a,@b=10,20  
> > end  
> > end  
> > =\> nil  
> > ary=[‘a’,‘b’]  
> > =\> [“a”, “b”]  
> > c=C.new  
> > =\> #\<C:0x2810628 @b=20, @a=10\>  
> > c.send(“a”,10)  
> > NoMethodError: undefined method `a' for #<C:0x2810628 @b=20, @a=10> from (irb):8:in `send’  
> > from (irb):8  
> > class C  
> > def initialize  
> > @a,@b=10,20  
> > end  
> > attr\_accessor :a, :b  
> > end  
> > =\> nil  
> > c.send(“a”,10)  
> > ArgumentError: wrong number of arguments(1 for 0)  
> > from (irb):15:in `a' from (irb):15:in `send’  
> > from (irb):15  
> > c.send(“a”+“=”,10)  
> > =\> 10  
> > c.a  
> > =\> 10

you may even use instance\_eval(“@a=”+value.to\_s)

> **···**
>
> il Sun, 18 Jan 2004 18:26:22 +0100, Bauduin Raphael [rb@raphinou.com](mailto:rb@raphinou.com) ha scritto::

---

<div class="post-metadata">

**Author:** ![Walter1](https://avatars.discourse-cdn.com/v4/letter/w/c77e96/32.png) [@Walter1](https://rubytalk.org/u/Walter1)\
**Post date:** [19 January 2004 00:40 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732/5 "2004-01-19T00:40:20Z")

</div>

> I saw in the pickaxe there’s a way to call methods dynamically, with  
> send(“method\_name”):
> 
> “test”.send(“length”) # 4
> 
> What I want to do is set a variable this way. Is it possible?

Using the following

class Q  
attr\_accessor :field  
end  
q = Q.new

here are some times for looping 1000000 times setting the index:  
i.e. 1.upto(1000000){|i| }

q.send(“field=”, i) took 2.203 seconds  
q.send(:field=, i) took 1.251 seconds  
q.instance\_eval{field = i} took 4.187 seconds  
q.instance\_variable\_set “@field”, i took 2.032 seconds  
q.instance\_variable\_set :@field, i took 1.072 seconds  
q.field = i took 0.921 seconds

P.S. These timings are for the PragProg installer  
ruby 1.8.0 (2003-08-04) [i386-mswin32]

Walt

> **···**
>
> * * *
> 
> Walter Szewelanczyk  
> IS Director  
> M.W. Sewall & CO. email : [walter@mwsewall.com](mailto:walter@mwsewall.com)  
> 259 Front St. Phone : (207) 442-7994 x 128  
> Bath, ME 04530 Fax : (207) 443-6284
> 
> * * *

---

<div class="post-metadata">

**Author:** ![Bauduin\_Raphael](https://avatars.discourse-cdn.com/v4/letter/b/b19c9b/32.png) [@Bauduin\_Raphael](https://rubytalk.org/u/Bauduin_Raphael)\
**Post date:** [18 January 2004 18:50 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732/6 "2004-01-18T18:50:03Z")

</div>

Thanks for the answers!

In my class I now use this :

```
instance_eval("@#{row[1]}=Translation.new(row)")

```

Raph

Mauricio Fernández wrote:

> **···**
>
> > On Mon, Jan 19, 2004 at 02:29:59AM +0900, Bauduin Raphael wrote:
> > 
> > > I saw in the pickaxe there’s a way to call methods dynamically, with  
> > > send(“method\_name”):
> > > 
> > > “test”.send(“length”) # 4
> > > 
> > > What I want to do is set a variable this way. Is it possible?
> > 
> > > > class A; end; a = A.new
> > 
> > =\> #\<A:0x401ff0d8\>
> > 
> > > > a.instance\_variable\_set :@foo, “foo”
> > 
> > =\> “foo”
> > 
> > > > a
> > 
> > =\> #\<A:0x401ff0d8 @foo=“foo”\>
> > 
> > > > a.instance\_variable\_get :@foo
> > 
> > =\> “foo”

---

<div class="post-metadata">

**Author:** ![Jim\_Weirich2](https://avatars.discourse-cdn.com/v4/letter/j/ecc23a/32.png) [@Jim\_Weirich2](https://rubytalk.org/u/Jim_Weirich2)\
**Post date:** [19 January 2004 12:46 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732/7 "2004-01-19T12:46:39Z")

</div>

gabriele renzi wrote:

> you may even use instance\_eval(“@a=”+value.to\_s)

Be aware that this only works when “value” has valid string  
representation that can be reliably converted back to an object. And  
then you only get a copy, not the original object.

The following will work with arbitrary objects …

obj.instance\_eval(“lambda { |v| @a = v }”).call(value)

At this point you must be thinking: “Why don’t I just use  
instance\_variable\_set?”

> **···**
>
> ## – – Jim Weirich [jweirich@one.net](mailto:jweirich@one.net)[http://onestepback.org](http://onestepback.org)
> 
> “Beware of bugs in the above code; I have only proved it correct,  
> not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)

---

<div class="post-metadata">

**Author:** ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://rubytalk.org/u/Robert)\
**Post date:** [19 January 2004 08:40 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732/8 "2004-01-19T08:40:00Z")

</div>

“Bauduin Raphael” [rb@raphinou.com](mailto:rb@raphinou.com) schrieb im Newsbeitrag  
[news:400ad514$0$1128$6c56d894@feed0.news.be.easynet.net](mailto:news:400ad514$0$1128$6c56d894@feed0.news.be.easynet.net)…

> Thanks for the answers!
> 
> In my class I now use this :
> 
> instance\_eval(“@#{row[1]}=Translation.new(row)”)

I’d prefer using “instance\_variable\_set” because that doesn’t require a  
setter method to be defined.

irb(main):007:0\> class Foo;end  
=\> nil  
irb(main):008:0\> f=Foo.new  
=\> #Foo:0x10182008  
irb(main):009:0\> f.instance\_variable\_set “@foo”, “bar”  
=\> “bar”  
irb(main):010:0\> f  
=\> #\<Foo:0x10182008 @foo=“bar”\>  
irb(main):011:0\>

With your code:

class Term  
attr :query, :fr, :nl, :en  
def initialize(dbh, id)  
@query = “select \* from translations where id=‘#{id}’”  
dbh.select\_all(query) do |row|  
instance\_variable\_set “@”+row[1], Translation.new(row)  
end  
end  
def get\_french()  
@fr.value  
end  
end

Regards

```
robert

```

---

<div class="post-metadata">

**Author:** ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://rubytalk.org/u/Robert)\
**Post date:** [19 January 2004 14:10 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732/9 "2004-01-19T14:10:00Z")

</div>

“Jim Weirich” [jweirich@one.net](mailto:jweirich@one.net) schrieb im Newsbeitrag  
[news:400BD300.3010906@one.net](mailto:news:400BD300.3010906@one.net)…

> gabriele renzi wrote:
> 
> > you may even use instance\_eval(“@a=”+value.to\_s)
> 
> Be aware that this only works when “value” has valid string  
> representation that can be reliably converted back to an object. And  
> then you only get a copy, not the original object.
> 
> The following will work with arbitrary objects …
> 
> obj.instance\_eval(“lambda { |v| @a = v }”).call(value)

Well, you can do it simpler, even if you _want_ to use instance\_eval. No  
need for a lambda:

irb(main):001:0\> class Foo  
irb(main):002:1\> def test(obj)  
irb(main):003:2\> instance\_eval(“@x=obj”)  
irb(main):004:2\> end  
irb(main):005:1\> end  
=\> nil  
irb(main):006:0\> f=Foo.new  
=\> #Foo:0x10197f08  
irb(main):007:0\> f.test “fff”  
=\> “fff”  
irb(main):008:0\> f  
=\> #\<Foo:0x10197f08 @x=“fff”\>  
irb(main):009:0\> f.test “xx”  
=\> “xx”  
irb(main):010:0\> f  
=\> #\<Foo:0x10197f08 @x=“xx”\>  
irb(main):011:0\> x=“hu!”  
=\> “hu!”  
irb(main):012:0\> f.instance\_eval “@y=x”  
=\> “hu!”  
irb(main):013:0\> f  
=\> #\<Foo:0x10197f08 @x=“xx”, @y=“hu!”\>  
irb(main):014:0\>

> At this point you must be thinking: “Why don’t I just use  
> instance\_variable\_set?”

I’d love to see the answer to this question you’d suggest. :-))

Cheers

```
robert

```

---

<div class="post-metadata">

**Author:** ![Martin\_Hart](https://avatars.discourse-cdn.com/v4/letter/m/54ee81/32.png) [@Martin\_Hart](https://rubytalk.org/u/Martin_Hart)\
**Post date:** [19 January 2004 15:12 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732/10 "2004-01-19T15:12:22Z")

</div>

running an earlier version of Ruby?  
My installation (1.6.8) does not appear to have this function.

> **···**
>
> On Monday 19 January 2004 14:10, Robert Klemme wrote:
> 
> > > At this point you must be thinking: “Why don’t I just use  
> > > instance\_variable\_set?”
> > 
> > I’d love to see the answer to this question you’d suggest. :-))
> 
> –  
> Martin Hart  
> Arnclan Limited  
> 53 Union Street  
> Dunstable, Beds  
> LU6 1EX  
> [http://www.arnclanit.com](http://www.arnclanit.com)

---

<div class="post-metadata">

**Author:** ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://rubytalk.org/u/Robert)\
**Post date:** [19 January 2004 15:50 UTC](https://rubytalk.org/t/setting-instance-variable-dynamically/9732/11 "2004-01-19T15:50:06Z")

</div>

“Martin Hart” [martin@zsdfherg.com](mailto:martin@zsdfherg.com) schrieb im Newsbeitrag  
[news:200401191504.29943.martin@zsdfherg.com](mailto:news:200401191504.29943.martin@zsdfherg.com)…

> **···**
>
> > On Monday 19 January 2004 14:10, Robert Klemme wrote:
> > 
> > > > At this point you must be thinking: “Why don’t I just use  
> > > > instance\_variable\_set?”
> > > 
> > > I’d love to see the answer to this question you’d suggest. :-))
> > 
> > running an earlier version of Ruby?  
> > My installation (1.6.8) does not appear to have this function.
> 
> That’s correctly observed. In that case using instance\_eval works better  
> by an order of magnitude.
> 
> Regards
> 
> ```
> robert
> 
> ```
