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.