使用块作为范围渲染倾斜模板

时间:2014-05-25 21:36:38

标签: ruby tilt

我使用template.erb作为我的模板示例,其中包含:<%= @text %>

我希望能够呈现范围为block的倾斜模板。

我已经完成了这项工作:

proc = Proc.new do
  @text = "Hello, World"
  Tilt.new('template.erb').render self
end
proc.call # => "Hello, World"

但是我想在模块之外渲染模板,如下所示:

proc = Proc.new do
  @text = "Hello, World"
end
tilt = Tilt.new('template.erb')
# I tried these alternatives:
tilt.render proc         # => ""
tilt.render proc.binding # => ""
tilt.render &proc        # => ""

然而,当我使用标准的ERB库时,我成功了:

proc = Proc.new do
  @text = "Hello, World"
  @num = 100
end
ERB.new('<%= @text %> | <%= @num %>').result proc.binding # => "Hello, World | 100"

我仍然喜欢使用Tilt,因为我想支持其他模板引擎。

1 个答案:

答案 0 :(得分:0)

  

然而,当我使用标准的ERB库时,我成功了:

proc = Proc.new do
  @text = "Hello, World"
  @num = 100
end

ERB.new('<%= @text %> | <%= @num %>').result proc.binding # => "Hello, World | 100"

如果我在代码的开头插入行require 'erb',并且如果我追加&#39; p&#39;到你的最后一行,我得到的输出是:

" | "

我在红宝石中测试过:1.8.7,1.9.3,2.0,2.1。

@text和@num为零的原因是因为它们不是proc绑定的一部分。首先,块中的代码(如def中的代码)在调用块之前甚至不执行,因此如果proc从未执行,则proc是空的还是@中的@变量没有区别。

其次,你的proc可以看到的唯一绑定(即周围范围中的变量及其值)是self = main。当@变量存在时,@变量将自身附加到自身的任何对象上。结果,当你的proc执行时,@变量将飞走并将自己附加到main,这意味着它们根本不会与你的proc相关联。

第三,你甚至无法在绑定中更改self的值:

class Dog
  def bark(proc_obj)
    #self is a dog instance in here
    proc_obj.call 
    p @text
  end
end


my_proc = Proc.new{@text = "hello"}
Dog.new.bark my_proc

puts @text

--output:--
nil 
hello

当proc执行时,在周围的范围内有一个名为self的变量,它的值是dog实例 - 但proc中的@变量将自身附加到self = main(最后一个puts语句显示)而不是自= dog_instance。对我来说,这表明self就像一个局部变量,并且proc在顶级范围内关闭名为self的局部变量。然后,在def ruby​​中创建另一个名为self的局部变量,其ruby设置等于调用def的dog实例。结果,def中的自我和自我是两个不同的变量,因此def中自我的值对proc看到的自身值没有影响。

最后,如果你查看ruby 2.1的文档,Binding类现在有一个从绑定中检索变量的方法,它被称为local_variable_get()。请注意名称​​ local 。没有名为instance_variable_get()的方法,因为据我所知,实例变量不是绑定的一部分 - 相反,它们会飞走并将自己附加到某个对象上,即无论自我在proc时是什么等于创建 - 而不是当proc执行时self等于。