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 Volkmann
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