GOAL: Values of an OpenStruct object should be printed as a hash rather than an object
POSSIBLE SOLUTION: Override getter of the OpenStruct class
MyOpenStruct overrides new, to_h and [] of OpenStruct.
class MyOpenStruct < OpenStruct
def initialize(object=nil)
@table = {}
@hash_table = {}
if object
object.each do |k,v|
if v.is_a?(Array)
other = Array.new()
v.each { |e| other.push(self.class.new(entry)) }
v = other
end
@table[k.to_sym] = (v.is_a?(Hash) ? self.class.new(v) : v)
@hash_table[k.to_sym] = v
new_ostruct_member(k)
end
end
end
def [](val)
@hash_table[val.to_sym]
end
end
But overriding [] is not making any difference. E.g.
irb(main):007:0> temp = MyOpenStruct.new({"name"=>"first", "place"=>{"animal"=>"thing"}})
=> #<MyOpenStruct name="first", place=#<MyOpenStruct animal="thing">>
irb(main):008:0> temp.name
=> "first"
irb(main):009:0> temp.place
=> #<MyOpenStruct animal="thing">
irb(main):010:0> temp["place"]
=> {"animal"=>"thing"}
irb(main):011:0> temp[:place]
=> {"animal"=>"thing"}
irb(main):012:0> temp
=> #<MyOpenStruct name="first", place=#<MyOpenStruct animal="thing">>
Only when I access the keys using [] a hash is returned!!
How can I correct this??
I don't believe create a nested OpenStruct makes sense if you are returning it as a Hash. That's the way OpenStruct works:
So, if you want to use the dot notation to get
struct.place.animal, you need to create nested OpenStruct objects like you did. But, as I said, you don't need to override the[]method. Using your class without override the[]I get this:Anyway, if you really want to make the dot notation work as you asked, you can override the
new_ostruct_membermethod, which is used internally to create dynamic attributes when setting the OpenStruct object. You can try something like this, but I don't recommend: