OpenStruct.new存储属性但不检索它

and*_*vom 4 ruby null openstruct

在创建一个新的Ruby OpenStruct对象之后,我能够存储属性但不能检索它们(我得到一个空行而是返回nil):

obj = OpenStruct.new # => #<OpenStruct>
obj.x = 10
obj.y = 20
obj                  # => #<OpenStruct x=10, y=20>
obj.x                # => 10
obj.y                #  
                     # => nil
Run Code Online (Sandbox Code Playgroud)

如果我尝试使用不同的名称存储其他属性,一切都按预期工作.这个问题似乎只有在我存储一个名为的属性时才会发生y.我使用以下版本:

ruby 1.9.2p320 (2012-04-20 revision 35421) [i686-linux]

有没有人知道发生了什么?

mu *_*ort 5

某些地方正在吸引PsychYAML的东西.心理补丁Kernel添加一个psych_y别名的方法y.所以,一切都有y定义的方法:

> o = OpenStruct.new
> o.method(:y)
 => #<Method: OpenStruct(Kernel)#psych_y> 
Run Code Online (Sandbox Code Playgroud)

AFAIK,OpenStruct使用method_missing和内部Hash生成访问器和mutator方法; 但是,已经存在一个y来自内核的"友好"补丁,因此OpenStruct的魔法无法处理该y方法,因为Psych的魔法正在阻碍.变异器y=虽然很好,但你可以安全地o.y = 11看到你的11内心o.

你可以删除y这样的:

> o = OpenStruct.new
> o.class_eval('undef_method :y')
> o.y = 11
> o.y
 => 11 
Run Code Online (Sandbox Code Playgroud)

你可以删除该方法,Kernel并希望没有任何东西取决于这个愚蠢的y别名:

> Kernel.send(:undef_method, :y)
> o = OpenStruct.new
> o.y = 11
> o.y
 => 11 
Run Code Online (Sandbox Code Playgroud)

或者您可以将其从OpenStruct以下位置删除:

> OpenStruct.send(:undef_method, :y)
> o = OpenStruct.new
> o.y = 11
> o.y
 => 11
Run Code Online (Sandbox Code Playgroud)

这就是为什么许多人不喜欢猴子修补,特别是猴子修补一些基本的东西Kernel.