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 })
我从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)
答案 0 :(得分:4)
所以绑定是在接收器的上下文中运行的,这是OpenStruct。
正确。
但是,模板如何获得
name
和last
?
不确定是什么让你感到困惑。当namespace
为self
时,方法name
和last
可用。因为他们是namespace
上的方法。然后将该绑定传递给ERB(因为它是instance_eval
的返回值)。这就是它如何得到它们。
答案 1 :(得分:1)
首先,#coding:UTF-8
_erbout = String.new
_erbout.concat "Name: "
_erbout.concat(( name ).to_s)
_erbout.concat " "
_erbout.concat(( last ).to_s)
_erbout.force_encoding(__ENCODING__)
将模板编译为包含以下内容的字符串:
"Name: #{name} #{last}"
大致相当于包含以下内容的字符串:
namespace
我正在使用后者(因为它更短)以及示例中的require 'ostruct'
namespace = OpenStruct.new(name: 'Joan', last: 'Maragall')
对象:
ERB#result
eval
现在只是eval
在给定绑定的上下文中使用此字符串:(注意双引号,eval('"Name: #{name} #{last}"', namespace.instance_eval { binding })
#=> "Name: Joan Maragall"
正在执行字符串插值)
eval
我们也可以将namespace.instance_eval { eval('"Name: #{name} #{last}"', binding) }
#=> "Name: Joan Maragall"
移到块中:
binding
使显式namespace.instance_eval { eval('"Name: #{name} #{last}"') }
#=> "Name: Joan Maragall"
多余:
namespace.instance_eval('"Name: #{name} #{last}"')
#=> "Name: Joan Maragall"
可以进一步简化为:
0