Adding an attribute to an object

I know how to add new methods to an existing object, but is there a way
to add an attribute?
I know I can do it if the object was created with ObjectStruct, but what
if it is a “normal” Ruby object?

R. Mark V.
Object Computing, Inc.

On Nov 14, 2007 6:10 PM, Mark V. [email protected] wrote:

I know how to add new methods to an existing object, but is there a way to add an attribute?
I know I can do it if the object was created with ObjectStruct, but what if it is a “normal” Ruby object?

R. Mark V.
Object Computing, Inc.

Not quite sure what you mean…but anyway, maybe this irb session will
help you along:

irb(main):001:0> class Dog; end
=> nil
irb(main):002:0> d = Dog.new
=> #Dog:0x2063cc
irb(main):003:0> Dog.class_eval { attr_accessor :name }
=> nil
irb(main):004:0> d.name = “Fido”
=> “Fido”
irb(main):005:0> (class << d; self; end).class_eval { attr_accessor :age
}
=> nil
irb(main):006:0> d.age = 12
=> 12
irb(main):007:0> d2 = Dog.new
=> #Dog:0x265afc
irb(main):008:0> d2.name = “Spike”
=> “Spike”
irb(main):009:0> d2.age = 7
NoMethodError: undefined method `age=’ for #<Dog:0x265afc @name=“Spike”>
from (irb):9
from :0

First we call attr_accessor for Dog, which defines #name and #name=
for all dogs. Then we define #age and #age= for only the one dog, by
calling attr_accessor on that object’s singleton class.

However, there’s not really a concept of “attributes” in Ruby (afaik).
attr_* are just macros that define methods that look like

class Dog
def age=(val)
@age = val
end

def age
@age
end
end

You can also dig in to an object with instance_eval and do your work:

irb(main):001:0> class Dog
irb(main):002:1> attr_reader :name
irb(main):003:1> end
=> nil
irb(main):004:0> d = Dog.new
=> #Dog:0x287eb8
irb(main):005:0> d.name
=> nil
irb(main):006:0> d.instance_eval { @name = “Spot” }
=> “Spot”
irb(main):007:0> d.name
=> “Spot”

hth

Pat

On Nov 14, 2007, at 7:10 PM, Mark V. wrote:

I know how to add new methods to an existing object, but is there a
way to add an attribute?
I know I can do it if the object was created with ObjectStruct, but
what if it is a “normal” Ruby object?

R. Mark V.
Object Computing, Inc.

cfp:~ > cat a.rb
require ‘attributes’ ### gem install attributes

o = Object.new

o.instance_eval{ attribute ‘foobar’ => 42 }

p o.foobar #=> 42

o.foobar = ‘forty-two’

p o.foobar #=> “forty-two”

p o.foobar? #=> “forty-two” (true)

o.foobar 42.0

p o.foobar #=> 42.0

cfp:~ > ruby a.rb
42
“forty-two”
“forty-two”
42.0

a @ http://codeforpeople.com/

On Nov 14, 7:10 pm, Mark V. [email protected] wrote:

I know how to add new methods to an existing object, but is there a way to add an attribute?
I know I can do it if the object was created with ObjectStruct, but what if it is a “normal” Ruby object?

As Pat pointed out, there are no ‘attributes’ in Ruby, just methods.
(Those methods may or may not have a 1-to-1 correspondence to instance
variables; that’s all the convenience methods like attr_accessor do,
is set up a simple method.)

irb(main):001:0> o = Object.new
=> #Object:0x1dbbf4
irb(main):002:0> def o.duration=( seconds )
irb(main):003:1> @length = seconds
irb(main):004:1> end
=> nil
irb(main):005:0> def o.duration; @length; end
=> nil
irb(main):006:0> o.duration = 120
=> 120
irb(main):007:0> puts o.duration
120
=> nil
irb(main):008:0> def o.duration_in_minutes; @length / 60; end
=> nil
irb(main):009:0> puts o.duration_in_minutes
2
=> nil