Question:
Using Ruby it is simple to add custom methods to existing classes, but how do you add custom properties? Here is an example of what I am trying to do:
myarray = Array.new();
myarray.concat([1,2,3]);
myarray._meta_ = Hash.new(); # obviously, this wont work
myarray._meta_['createdby'] = 'dreftymac';
myarray._meta_['lastupdate'] = '1993-12-12';
## desired result
puts myarray._meta_['createdby']; #=> 'dreftymac'
puts myarray.inspect() #=> [1,2,3]
The goal is to construct the class definition in such a way that the stuff that does not work in the example above will work as expected.
Update: (clarify question) One aspect that was left out of the original question: it is also a goal to add “default values” that would ordinarily be set-up in the initialize method of the class.
Update: (why do this) Normally, it is very simple to just create a custom class that inherits from Array (or whatever built-in class you want to emulate). This question derives from some “testing-only” code and is not an attempt to ignore this generally acceptable approach.
Recall that in Ruby, you do not have access to attributes (instance variables) outside of that instance. You only have access to an instance’s public methods.
You can use
attr_accessorto create a method for a class that acts as a property as you describe:For a simple way to do a default initialization for an accessor, we’ll need to basically reimplement
attr_accessorourselves:But wait! The output is incorrect:
We’ve created a closure around the default value of a literal hash.
A better way might be to simply use a block:
Now the output is correct because
Hash.newis called every time the default value is retrieved, as opposed to reusing the same literal hash every time.