After creating a new Ruby OpenStruct object, I am able to store attributes but not to retrieve them (I get a blank line and it returns nil
instead):
obj = OpenStruct.new # => #<OpenStruct>
obj.x = 10
obj.y = 20
obj # => #<OpenStruct x=10, y=20>
obj.x # => 10
obj.y #
# => nil
If I try to store other properties with different names, everything works as expected. This problem seems to happen only when I store a property named y
. I'm using the following version:
ruby 1.9.2p320 (2012-04-20 revision 35421) [i686-linux]
Does anybody have an idea of what's going on?
Something somewhere is pulling in Psych
for YAML stuff. Psych patches Kernel
to add a psych_y
method which is aliased to y
. So, everything has a y
method defined:
> o = OpenStruct.new
> o.method(:y)
=> #<Method: OpenStruct(Kernel)#psych_y>
AFAIK, OpenStruct uses method_missing
and an internal Hash to produce accessor and mutator methods; but, there's already a y
from that "friendly" patch to Kernel so OpenStruct's magic doesn't get to handle the y
method because Psych's magic is in the way. The mutator, y=
, is fine though so you can safely o.y = 11
and see your 11
inside o
.
You could remove the y
like this:
> o = OpenStruct.new
> o.class_eval('undef_method :y')
> o.y = 11
> o.y
=> 11
You could probably remove the method from Kernel
and hope that nothing depends on that silly y
alias:
> Kernel.send(:undef_method, :y)
> o = OpenStruct.new
> o.y = 11
> o.y
=> 11
Or you could just remove it from OpenStruct
:
> OpenStruct.send(:undef_method, :y)
> o = OpenStruct.new
> o.y = 11
> o.y
=> 11
This sort of thing is why a lot of people don't like monkey patching, especially monkey patching something as fundamental as Kernel
.