gpt4 book ai didi

ruby - 使用 define_singleton_method 创建的赋值方法返回错误值

转载 作者:数据小太阳 更新时间:2023-10-29 07:31:54 26 4
gpt4 key购买 nike

背景

实体类是一个基类,由多个子类继承,这些子类保存通过 REST API 接收的实体。实体类是不可变的,每当尝试更改时都应返回其自身的新实例。

Entity 类有一个 .update() 方法,它接受一个散列值来更新,如果变化不是真正的变化它返回它自己,如果有真正的变化它返回一个新的自身的实例,并在实例化之前进行更改。

为了用户友好,实体还允许直接分配给属性(这样,如果实体的子类具有名称属性,您可以执行 instance.name = 'New Name'),同时返回一个类的新实例。这是通过使用实例化类时创建的动态方法的更新来实现的。

他们就是问题所在。

问题

Entity 类中的代码部分看起来像这样(有关完整的代码 list 和测试,请查看 Github 存储库:https://github.com/my-codeworks/fortnox-api.git):

require "virtus"
require "ice_nine"

class Entity

extend Forwardable
include Virtus.model

def initialize( hash = {} )
super
create_attribute_setter_methods
IceNine.deep_freeze( self )
end

def update( hash )
attributes = self.to_hash.merge( hash )
return self if attributes == self.to_hash
self.class.new( attributes )
end

private

def create_attribute_setter_methods
attribute_set.each do |attribute|
name = attribute.options[ :name ]

create_attribute_setter_method( name )
end
end

def create_attribute_setter_method( name )
self.define_singleton_method "#{name}=" do | value |
self.update( name => value )
end
end

end

这样做:

instance.update( name: 'New Name' )

还有这个:

instance.name = 'New Name'

从字面上看应该是一样的,因为一个是根据另一个实现的。

虽然 .update() 完美运行,但 .attr=() 方法返回您分配的值。

因此在上面的示例中,.update() 返回了 Entity 子类的一个新实例,但是 .attr=() 返回了 'New Name' ...

我尝试在 .attr=() 方法中捕获输出并在返回之前记录它,这样我就有了:

self.define_singleton_method "#{name}=" do | value |
p "Called as :#{name}=, redirecting to update( #{name}: #{value} )"
r = self.update( name => value )
p "Got #{r} back from update"
return r
end

日志行说:

 "Called as :name=, redirecting to update( name: 'New Name' )"
"Got #<TestEntity:0x007ffedbd0ad18> back from update"

但我得到的只是字符串'New Name'...

我的前额流血了,我发现没有任何帖子显示与此相近的内容。我敢打赌我做错了什么,但我找不到它。

变脏

Github 存储库在 rspec 中有您可以运行的测试,失败的测试现在是重点,实体类中有一些额外的日志记录以捕获不同的内部步骤。

欢迎评论、链接和/或拉取请求。

最佳答案

事实证明,= 方法总是返回分配的值。

o = Struct.new(:key).new(1)
o.define_singleton_method("something") { @something }
o.define_singleton_method("something=") do |v|
@something = v
return 6
end

如您所见,每次调用 something= 时,我都将返回值“固定”为 6。让我们看看它是否有效:

o.something = 1 #=> outputs 1, not 6
o.something #=> outputs 1, so the method did indeed run

结论?我的猜测是 = 方法将返回您通过它分配的值。在我看来,这样更好;一个原因是为了确保分配链的正常运行:

new_val = o.something = some_val

关于ruby - 使用 define_singleton_method 创建的赋值方法返回错误值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29795526/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com