I can't understand why this code works fine
def func
ERB.new('<%= yield %>').result(binding)
end
func { 123 } # => it prints 123 as expected
but this one doesn't work and raises an exception
ERB.new('<%= yield %>').result(binding) { 123 } # => LocalJumpError: no block given (yield)
Any thoughts?
This problem is independent of ERB and is because of the way yield works. Yield expects to be called within the message body and expects a block to yield it. Let's take this example
# This is equivalent to
# def func
# ERB.new('<%= yield %>').result(binding)
# end
def test_print
yield
end
If we call the method without a block
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>
If we call the method with block
irb(main):039:0> test_print { "hello world" }
=> "hello world"
irb(main):040:0>
In the latter case
ERB.new('<%= yield %>').result(binding) { 123 }
Your block is not being passed as yield is outside the message body and you cannot do
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>
You should pass a block to the method context, where is binding called, e.g.:
def foo
binding
end
ERB.new('<%= yield %>').result(foo { 123 })
#=> "123"
Note, that you cannot use yield outside of a method body.
ERB#result just executes ruby code in context of passed binding, so binding in your should be inside the method anyway, because of yield.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With