4

创建一个新的 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

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

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

有人知道发生了什么吗?

4

1 回答 1

5

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

> o = OpenStruct.new
> o.method(:y)
 => #<Method: OpenStruct(Kernel)#psych_y> 

AFAIK,OpenStruct 使用method_missing内部哈希来生成访问器和修改器方法;但是,已经有一个y来自内核的“友好”补丁,因此 OpenStruct 的魔法无法处理该y方法,因为 Psych 的魔法阻碍了。mutatory=很好,所以你可以安全地o.y = 11看到你的11内部o

你可以删除y这样的:

> o = OpenStruct.new
> o.class_eval('undef_method :y')
> o.y = 11
> o.y
 => 11 

您可能可以从中删除该方法,Kernel并希望没有什么依赖于那个愚蠢的y别名:

> Kernel.send(:undef_method, :y)
> o = OpenStruct.new
> o.y = 11
> o.y
 => 11 

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

> OpenStruct.send(:undef_method, :y)
> o = OpenStruct.new
> o.y = 11
> o.y
 => 11

这就是为什么很多人不喜欢猴子补丁的原因,尤其是猴子补丁这样基本的东西Kernel

于 2012-11-04T18:27:50.253 回答