在这种情况下 instance_eval 是如何工作的?到底是怎么回事?

Jwa*_*622 1 ruby

instance_eval当它通过绑定时会做什么?我对这段代码感到困惑:

require 'erb'
require 'ostruct'
namespace = OpenStruct.new(name: 'Joan', last: 'Maragall')
template = 'Name: <%= name %> <%= last %>'
result = ERB.new(template).result(namespace.instance_eval { binding })
Run Code Online (Sandbox Code Playgroud)

我从文档中读到instance_eval:z

在接收器 (obj) 的上下文中评估包含 Ruby 源代码或给定块的字符串。为了设置上下文,在代码执行时将变量 self 设置为 obj,使代码可以访问 obj 的实例变量。

所以binding在接收者的上下文中运行,即OpenStruct. 但是模板是如何获得name和的last呢?我感觉我少了一步。

也就是说,我很困惑为什么会发生这种情况:

result = ERB.new(template).result(namespace)
TypeError: wrong argument type OpenStruct (expected binding)
Run Code Online (Sandbox Code Playgroud)

Ser*_*sev 5

因此绑定在接收者的上下文中运行,即 OpenStruct。

正确的。

但是模板是如何获得name和的last呢?

不知道是什么让你感到困惑。如果namespaceself,方法namelast可用。因为它们是namespace. 然后将该绑定传递给 ERB(因为它是 的返回值instance_eval)。这就是它获得它们的方式。

  • @Jwan622 您需要一个绑定,因为 `ERB#result` 需要一个绑定作为参数。你不能传递当前上下文的绑定(即`ERB.new(template).result(binding)`),因为`name` 和`last` 将不可用。您需要来自`namespace` 的绑定。如何从其他对象中获取绑定?`obj.instance_eval {binding}`。 (2认同)