在一个类的主体内部,我想将一个块传递给一个名为with
的方法。对于块的生命周期,我希望with_value
方法可用。
否则,块内的所有内容都应该像在块外面一样。
以下是一个例子:
class C
extend M
with "some value" do
do_something_complicated
do_something_complicated
do_something_complicated
end
end
我们几乎得到这个:
module M
def with(str, &block)
Object.new.tap do |wrapper|
wrapper.define_singleton_method :with_value do # Here's our with_value
str # method.
end
end.instance_eval &block
end
def do_something_complicated # Push a value onto an
(@foo ||= []).push with_value # array.
end
end
但存在问题:由于我们正在评估在不同对象的上下文中传递给with
的块,do_something_complicated
不可用。
什么是解决这个问题的正确方法?
答案 0 :(得分:3)
这将使with_value
仅在块内可用。但是,_with_value
将在块内部或外部定义。
module M
def _with_value
...
end
def with(str, &block)
alias with_value _with_value
block.call
undef with_value
end
...
end
我无法从问题中判断这是否是一个问题。如果这是一个问题,你需要进一步描述你想要做的事情。
答案 1 :(得分:1)
基本上,我们的想法是使用method_missing
将方法调用从伪类转发到调用类。如果您还需要访问实例变量,可以将它们从调用类复制到虚拟类,然后在块返回后再将它们复制。
Ruby gem docile
是这种系统的一个非常简单的实现。我建议你阅读该存储库中的源代码(不用担心,这是一个非常小的代码库),以获得一个很好的例子,说明像你的示例中的方法一样有效。
答案 2 :(得分:0)
这是一种更接近你的尝试的方式:
module M
def with(str, &block)
dup.tap do |wrapper|
wrapper.define_singleton_method :with_value do
...
end
end.instance_eval &block
end
...
end
dup
将复制从with
作为类方法调用的类。