Template variables arguments and methods

I have a question about Chef templates, variables arguments, and methods. When using templates in a recipe, I sometimes want to use a method instead of a local variable as the value to variable key. ex. def baz { ‘baz’ } vs baz = ‘baz’. When I try to use baz as a method in the template variables section, using the syntax of #1 and #2, Chef fails to converge the template and raises an undefined method error for baz. For #1 and #2 if baz is a local variable in the template it works fine. Today I discovered syntax #4 which worked when baz is a method.

I’m going to show my own ignorance about Ruby now. I understand { bar: ‘b’ } to be a Hash in Ruby. So I think #1 is passing a Hash to a “variables” method on a template object. For #2 I was guessing it was coercing the list of arguments into a Hash (kind of like varargs in Java). For #3 I was guessing it’s evaluating the outer {} as a block and the inner {} as a Hash. Can you confirm these assumptions?

So why do #1 and #2 raise an undefined method error and #3 works. It seems the Chef/Template DSL is treating methods differently than local variables when it comes to templates.

def baz
’baz’
end

  1. Parentheses then braces

template ‘foo’ do
variables({
bar: baz,
a: ‘b’,
})
end

  1. Parentheses and no braces

template ‘foo’ do
variables(
bar: baz,
a: ‘b’,
)
end

  1. Double braces

template ‘foo’ do
variables{{
bar: baz,
a: ‘b’,
}}
end

Thanks,

Brandon Richins