我正在尝试将局部变量设置为现有绑定
def foo_callback
lambda { |name| p name }
end
b = foo_callback.binding
绑定没有任何开始的局部变量:
b.eval("local_variables") # => []
让我们将原始局部变量设置为绑定:
b.eval("age=30")
一切都按预期工作:
b.eval("local_variables") # => ["age"]
b.eval("age") # => 30
现在,让我们尝试将非原始局部变量设置为绑定:
country = Country.first
b.eval("lambda {|v| country = v}").call(country)
注意:设置变量的technique来自facet
gem。我尝试了ruby 1.9 safe implementation,结果相同。
绑定不反映局部变量country
。
b.eval("local_variables") # => ["age"]
如何解决此问题?基本上,我想使用现有的非原始变量的值在绑定中声明一个新变量。
我在Ruby 1.8.7上。
答案 0 :(得分:5)
您在绑定之外创建country
,然后country
内的lambda
仅在该范围内有效。为什么不eval
如果你需要将它注入到绑定中呢?
<强>更新强>
尝试将变量声明在lambda
范围之外,但在绑定范围内:
b.eval("country = nil; lambda {|v| country = v}").call(country)
答案 1 :(得分:2)
这里的问题是你在另一个lambda中创建了一个新的lambda,并且正在创建一个新的范围。
更明确地说,绑定“b”将在其范围内具有函数#foo_callback范围内可用的所有局部变量,以及第一个lambda中可用的所有局部变量。您创建的第二个lambda是一个新范围,因此在该范围内创建的新局部变量不会在范围之外保留,除非它们首先在内部范围之外进行初始化。
这就是为什么你会看到很多人在进入块之前将局部变量初始化为nil。你也可以做同样的事情:
country = country
{...block that sets country to something non-nil...}
return country
实例变量没有此范围问题,并且可以在函数的内部和外部范围内使用。
前:
b.eval("lambda {|c| @country = c}").call(country)
b.eval "instance_variables"
应该有用。
而且,当我写这篇文章时,有人打败了我的答案:)