# Using dynamic method calling with attr\_writer methods

**URL:** <https://www.ruby-forum.com/t/using-dynamic-method-calling-with-attr-writer-methods/103747>\
**Category:** Ruby\
**Created:** [May 9, 2007, 9:23pm UTC](https://www.ruby-forum.com/t/using-dynamic-method-calling-with-attr-writer-methods/103747 "2007-05-09T21:23:56Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![daisagah](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b4bc9f/32.png) [@daisagah](https://www.ruby-forum.com/u/daisagah)\
**Post date:** [May 9, 2007, 9:23pm UTC](https://www.ruby-forum.com/t/using-dynamic-method-calling-with-attr-writer-methods/103747/1 "2007-05-09T21:23:56Z")

</div>

I’m a total Ruby newbie looking for help.

I’m writing an application where I need to dynamical assign object  
variables via attr\_writer object methods.

My code is something like this:

class Test \< ParentClass  
attr\_reader :one, :two, :three  
attr\_writer :one, :two, :three

```
   def initialize
      super
   end

```

end  
( I know I could use attr\_accessor but for testing I’ll stick to  
attr\_writer and \_reader)

Now I try to call the ‘Test’ methods dynamical witch ‘object.send’ from  
within my main application:

[…]

@methods = [‘one’, ‘two’, ‘three’]

test = Test.new

@methods.each { |a| test.send(a, ‘foo’) }

[…]

This throws the error: ArgumentError: wrong number of Arguments (1 for  
0)

As far as I understand, this is the correct behaviour. Because without  
the second argument, the method call returns the value of the class  
variable. So I believe, that this should work if i’ll write all the  
setter and getter methods myself (which I don’t want to, because I’m  
using a lot of variables).  
Are there any other methods I can use to dynamically call attr\_writer  
methods to assign values to the class variables or did I get something  
wrong and made a mistake?

---

<div class="post-metadata">

**Author:** ![daisagah](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b4bc9f/32.png) [@daisagah](https://www.ruby-forum.com/u/daisagah)\
**Post date:** [May 9, 2007, 9:35pm UTC](https://www.ruby-forum.com/t/using-dynamic-method-calling-with-attr-writer-methods/103747/2 "2007-05-09T21:35:42Z")

</div>

On 5/9/07, Markus H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> attr_writer :one, :two, :three
> 
> ```
> 
> within my main application:
> 
> wrong and made a mistake?
> 
> –  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

I’m pretty new to ruby too, but from what I understand, the writer  
methods  
will be called one=, two=, etc

So changing that @methods array to include the equals should fix your  
problem

Hope this helps,  
Nick

---

<div class="post-metadata">

**Author:** ![daisagah](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b4bc9f/32.png) [@daisagah](https://www.ruby-forum.com/u/daisagah)\
**Post date:** [May 9, 2007, 9:38pm UTC](https://www.ruby-forum.com/t/using-dynamic-method-calling-with-attr-writer-methods/103747/3 "2007-05-09T21:38:44Z")

</div>

On May 9, 2007, at 3:23 PM, Markus H. wrote:

> I’m a total Ruby newbie looking for help.  
> […]  
> @methods.each { |a| test.send(a, ‘foo’) }

> This throws the error: ArgumentError: wrong number of Arguments (1 for  
> 0)

The problem is you are calling the ‘getters’ with an argument (‘foo’).  
Getters don’t take an argument, thus the error message. You want:

```
@methods.each { |a| puts test.send(a) }

```

I added the puts, otherwise you won’t get any output.

If you want to call the setters, you need to send a different method  
name:

```
@methods.each { |a| test.send("#{a}=", 'foo') }

```

And of course you need to send an argument also.

Gary W.

---

<div class="post-metadata">

**Author:** ![daisagah](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b4bc9f/32.png) [@daisagah](https://www.ruby-forum.com/u/daisagah)\
**Post date:** [May 9, 2007, 10:10pm UTC](https://www.ruby-forum.com/t/using-dynamic-method-calling-with-attr-writer-methods/103747/4 "2007-05-09T22:10:04Z")

</div>

> The problem is you are calling the ‘getters’ with an argument (‘foo’).  
> Getters don’t take an argument, thus the error message. You want:
> 
> ```
> @methods.each { |a| puts test.send(a) }
> 
> ```
> 
> I added the puts, otherwise you won’t get any output.

Yep, this works perfectly. I already tested this.

> If you want to call the setters, you need to send a different method  
> name:
> 
> ```
> @methods.each { |a| test.send("#{a}=", 'foo') }
> 
> ```
> 
> And of course you need to send an argument also.

That’s it!! Thanks. Now everything works as expected. Allthough I like  
mine better, seems more  
logical to me ;).

---

<div class="post-metadata">

**Author:** ![daisagah](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b4bc9f/32.png) [@daisagah](https://www.ruby-forum.com/u/daisagah)\
**Post date:** [May 10, 2007, 12:41am UTC](https://www.ruby-forum.com/t/using-dynamic-method-calling-with-attr-writer-methods/103747/5 "2007-05-10T00:41:06Z")

</div>

On May 9, 2:10 pm, Markus H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> That’s it!! Thanks. Now everything works as expected. Allthough I like  
> mine better, seems more  
> logical to me ;).

Well, you can do that too, if you like:

class Module  
def attr\_readwrite( \*methods )  
class\_eval{  
methods.each{ |method\_name|  
define\_method( method\_name ){ |\*val|  
val = val.first  
unless val.nil?  
instance\_variable\_set( “@#{method\_name}”, val )  
else  
instance\_variable\_get( “@#{method\_name}” )  
end  
}  
}  
}  
end  
end

class Foo  
attr\_readwrite :foo, :bar  
end

f = Foo.new

f.foo( 42 )  
p f.foo  
#=\> 42  
f.foo( 12 )  
p f.foo  
#=\> 12

(I think there’s a more elegant way to define the method and detect if  
it received a value, but I was too lazy to figure it out.)

I’m pretty sure Ara T. Howard’s ‘attributes’ gem also gives you the  
ability to do what you want, where calling the method without a  
parameter acts as a getter, and calling it with a parameter acts as a  
setter. And I bet his way is clean. 🙂
