Setting attribute via send in Ruby 1.8.6

C

Charles Calvert

Using Ruby 1.8.6.

I've run into an instance in which I'd like to set attributes of an
instance using the send method. I've looked around, but found
nothing, most likely because I'm using the wrong search terms.

Example:

class A
attr_reader :foo
attr_writer :foo
end

a = A.new
a.send("foo", "newval")


I get the following error: "wrong number of arguments (1 for 0)
(ArgumentError)"

Am I correct in thinking that this is possible, and that I'm just
going about it the wrong way?
 
R

Robert Klemme

Using Ruby 1.8.6.

I've run into an instance in which I'd like to set attributes of an
instance using the send method. I've looked around, but found
nothing, most likely because I'm using the wrong search terms.

Example:

class A
attr_reader :foo
attr_writer :foo
end

a = A.new
a.send("foo", "newval")


I get the following error: "wrong number of arguments (1 for 0)
(ArgumentError)"

Am I correct in thinking that this is possible, and that I'm just
going about it the wrong way?

Yes.

....












:)

You need to use the _setter_ method with #send - which happens to be
called "foo=" in your case.

Kind regards

robert
 
S

Stefano Crocco

|Using Ruby 1.8.6.
|
|I've run into an instance in which I'd like to set attributes of an
|instance using the send method. I've looked around, but found
|nothing, most likely because I'm using the wrong search terms.
|
|Example:
|
|class A
| attr_reader :foo
| attr_writer :foo
|end
|
|a = A.new
|a.send("foo", "newval")
|
|
|I get the following error: "wrong number of arguments (1 for 0)
|(ArgumentError)"
|
|Am I correct in thinking that this is possible, and that I'm just
|going about it the wrong way?
|

The method attr_writer generates has an equal sign appended to the name you
give. This means that

attr_writer :foo

generates a method called foo=. So, if you want to call it using send, you
need to write:

a.send("foo=", "newval")

I hope this helps

Stefano
 
C

Charles Calvert

[snip example]

The suspense almost killed me!
:)

You need to use the _setter_ method with #send - which happens to be
called "foo=" in your case.

Ah, now the lightbulb goes off. I should have remembered the
convention of having the setter have an equals sign as part of the
name. I'm too used to languages that determine which accessor is used
based on which side of the assignment it appears rather than actually
using a method name to syntactically simulate assignment.

Thanks for the help.
 
J

Jesús Gabriel y Galán

[snip example]

The suspense almost killed me!
:)

You need to use the _setter_ method with #send - which happens to be
called "foo=3D" in your case.

Ah, now the lightbulb goes off. =A0I should have remembered the
convention of having the setter have an equals sign as part of the
name. =A0I'm too used to languages that determine which accessor is used
based on which side of the assignment it appears rather than actually
using a method name to syntactically simulate assignment.

You can achieve what you want if instead of using attr_writer you roll your=
own.
I remember a discussion in this list regarding something like:

class A
def a *args
return @a if args.empty?
@a =3D args[0]
end
end

a =3D A.new
a.a #=3D> nil
a.a 4 #=3D> 4
a.a #=3D> 4

With this you can do a.send:)a, 4)

Jesus.
 
R

Robert Gleeson

Hello,
Example:

class A
attr_reader :foo
attr_writer :foo
end

You can accomplish this is one line with attr_accessor :foo .
I think every poster has said this, but attr_reader defines:

class A

def foo
@foo
end

end

While attr_writer defines:

class A

def foo= value
@foo = value
end

end

Hope this helps,
Rob
 
R

Robert Klemme

On 10/23/2009 05:10 PM, Charles Calvert wrote:
Using Ruby 1.8.6.

I've run into an instance in which I'd like to set attributes of an
instance using the send method. I've looked around, but found
nothing, most likely because I'm using the wrong search terms.
[snip example]
I get the following error: "wrong number of arguments (1 for 0)
(ArgumentError)"

Am I correct in thinking that this is possible, and that I'm just
going about it the wrong way?
Yes.

...
The suspense almost killed me!

I'm glad I did not extend the pause even more. :)
Ah, now the lightbulb goes off. I should have remembered the
convention of having the setter have an equals sign as part of the
name. I'm too used to languages that determine which accessor is used
based on which side of the assignment it appears rather than actually
using a method name to syntactically simulate assignment.

You can achieve what you want if instead of using attr_writer you roll your own.
I remember a discussion in this list regarding something like:

class A
def a *args
return @a if args.empty?
@a = args[0]
end
end

a = A.new
a.a #=> nil
a.a 4 #=> 4
a.a #=> 4

With this you can do a.send:)a, 4)

This also has the added advantage to be easier with #instance_eval, i.e.
you can then do

obj = A.new
obj.instance_eval do
a 10
end

If you had to use a= in the block you would have to write "self.a = 10"
in order to prevent recognition of "a" as a local variable.

Nevertheless, the general convention is to use a=. Btw, you could even
create a custom attr_accessor method that will create both variants so
you can do

obj.a # getter
obj.a = 10 # setter
obj.a(10) # setter

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top