adding attributes to a Ruby object dynamically

I have an object created, and I want, based on some conditional check, to add some attributes to this object. How can I do this? To explain what I want:

A=Object.new
if(something happens)
{
  #make A have another attibute say age
  #& store something in A.age

}

First of all the thing about ruby is that it allows a different syntax which is used widely by ruby coders. Capitalized identifiers are Classes or Constants (thanks to sepp2k for his comment), but you try to make it an object. And almost nobody uses {} to mark a multiline block.

a = Object.new
if (something happens)
  # do something
end

I'm not sure what your question is, but I have an idea, and this would be the solution:

If you know what attributes that class can have, and it's limited you should use

class YourClass
  attr_accessor :age
end

attr_accessor :age is short for:

def age
  @age
end
def age=(new_age)
  @age = new_age
end

Now you can do something like this:

a = YourClass.new
if (some condition)
  a.age = new_value
end

If you want to do it completely dynamically you can do something like this:

a = Object.new
if (some condition)
  a.class.module_eval { attr_accessor :age}
  a.age = new_age_value
end

You could use an OpenStruct:

a = OpenStruct.new
if condition
    a.age = 4
end

Or just use a plain old hash.


This adds the attribute to only the object:

a = Object.new
if (something happens)
  class << a
    attr_accessor :age
  end
  a.age = new_age_value
end

If the name of the attribute is known at code-writing time then you can do what was suggested already:

class A
end

a = A.new
a.age = 20 # Raises undefined method `age='

# Inject attribute accessors into instance of A
class << a
  attr_accessor :age
end

a.age = 20 # Succeeds
a.age # Returns 20

b = A.new
b.age # Raises undefined method, as expected, since we only modified one instance of A

However, if the attribute's name is dynamic and only known at runtime then you'll have to call attr_accessor a bit differently:

attr_name = 'foo'

class A
end

a = A.new
a.foo = 20 # Raises undefined method `foo='

# Inject attribute accessors into instance of A
a.instance_eval { class << self; self end }.send(:attr_accessor, attr_name)

a.foo = 20 # Succeeds
a.foo # Returns 20

You can use instance_variable_set to set a variable on an instance of the Object class (and instance_variable_get to get it.) The Object class doesn't have any attributes you can set directly.

However, I suspect this is not the best solution for what you are trying to achieve; it is not the norm to directly work with the Object class, but rather to define or use classes that inherit from it, that have the attributes you want to work with.