将局部变量注入绑定

时间:2012-03-12 18:40:02

标签: ruby-on-rails ruby

我正在尝试将局部变量设置为现有绑定

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上。

2 个答案:

答案 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"

应该有用。

而且,当我写这篇文章时,有人打败了我的答案:)