带有yield的Ruby erb模板

时间:2017-10-09 17:45:49

标签: ruby erb yield

我无法理解为什么这段代码可以正常运行

def func
  ERB.new('<%= yield %>').result(binding)
end
func { 123 } # => it prints 123 as expected

但是这个不起作用并引发异常

ERB.new('<%= yield %>').result(binding) { 123 } # => LocalJumpError: no block given (yield)

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

这个问题与ERB无关,是因为yield的工作方式。 期望在消息正文中调用Yield,并期望一个块产生它。让我们举个例子

# This is equivalent to 
# def func
# ERB.new('<%= yield %>').result(binding)
# end

def test_print
  yield
end

如果我们调用没有块的方法

irb(main):038:0> test_print
LocalJumpError: no block given (yield)
    from (irb):36:in `test_print'
    from (irb):38
    from /Users/agupta/.rvm/rubies/ruby-2.4.0/bin/irb:11:in `<main>'
irb(main):039:0>

如果我们用块

调用该方法
irb(main):039:0> test_print { "hello world" }
=> "hello world"
irb(main):040:0>

在后一种情况下

ERB.new('<%= yield %>').result(binding) { 123 } 

由于yield位于邮件正文之外且您无法执行

,因此未传递您的阻止
irb(main):042:0> yield.tap { "hello world" }
LocalJumpError: no block given (yield)
    from (irb):42
    from /Users/agupta/.rvm/rubies/ruby-2.4.0/bin/irb:11:in `<main>'
irb(main):043:0>

答案 1 :(得分:3)

您应该将块传递给方法上下文,其中binding被调用,例如:

def foo
  binding
end

ERB.new('<%= yield %>').result(foo { 123 })
#=> "123"

请注意,您不能在方法正文之外使用yieldERB#result只是在传递绑定的上下文中执行ruby代码,因此你的绑定应该在方法内部,因为yield