Using dynamic method calling with attr_writer methods

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?

On 5/9/07, Markus H. [email protected] wrote:

   attr_writer :one, :two, :three

within my main application:

wrong and made a mistake?


Posted via 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

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.

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 ;).

On May 9, 2:10 pm, Markus H. [email protected] 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. :slight_smile: