Chef非常适合配置基本模板,但我希望采用更高级的模板逻辑。这样的事情是可能的:
<%
def say_hi()
-%>
<%= "hi" %>
<%
end
-%>
# Extraneous template data here
<% say_hi() -%> # Call to template method
在这个示例中,我希望每当调用hi
时都会生成say_hi()
,但它不起作用。
这种行为是否可行,如果没有,是否有办法产生类似的行为?我假设Chef模板遵循通用的ERB模板规则。
谢谢!
更新:一点背景故事
我正试图模仿一个非常复杂的config.yml
,它有自己的格式化方案。它看起来像这样:
key: value
some other key:
- some other value
- another value
hash-like key:
hash-like value:
- element A
- element B
有这么多,我认为不是直接在线映射属性,我会在公共密钥下定义它们并循环遍历它们:
<% node['section']['help'].each do |key, value| -%>
<%= "#{key}: #{value}" %>
<% end -%>
这很棒!它使我不必定义所有内容两次(一次在属性文件中,一次在模板中),但我觉得这种结构失控,特别是对于数组中的嵌套哈希:
<% node['section']['help'].each do |key, value| -%>
<% if value.kind_of?(Hash) -%>
<%= "#{key}: "%>
<% value.each do |subkey, subvalue| -%>
<%= " #{subkey}: #{subvalue}" %>
<% end -%>
<% else -%>
<%= "#{key}: #{value}" %>
<% end -%>
<% end -%>
所以我想创建一个递归方法来识别三种类型(正常值,数组值和哈希值)并处理每种类型的格式。我原型的完整方法看起来像这样:
<%
def determine_type(key, value, iteration)
if value.kind_of?(Hash)
-%>
<%= %Q(#{" " * (iteration * 2)} #{key}:) %>
<% value.keys do |subkey, subvalue| -%>
<% determine_type(subkey, subvalue, iteration + 1) -%>
<% end -%>
<%
elsif value.kind_of?(Array)
-%>
<%= %Q(#{" " * (iteration * 2)} #{key}:) %>
<% value.each do |subvalue| -%>
<%= %Q(#{" " * ((iteration + 1) * 2)} - #{subvalue}) %>
<% end -%>
<%
else
-%>
<%= %Q(#{" " * (iteration * 2)} #{key}: #{value}) %>
<%
end
end
-%>
它在这里被称为:
<% node['section']['help'].each do |key, value| -%>
<% determine_type(key, value, 1) -%>
<% end -%>
可悲的是,如果只能返回值而不能直接输出到ERB模板,那么这种相对优雅的策略就会中断。
答案 0 :(得分:1)
这不是推荐的设计模式。逻辑应该保存在食谱和资源中。这说明你的问题很可能是什么,以及什么使我的兴趣达到顶峰
<%
def say_hi()
-%>
<% "hi" %>
<%
end
-%>
# Extraneous template data here
<%= say_hi() -%> # Call to template method
将呈现以下文件
# Extraneous template data here
hi # Call to template method
注意<%=
块如何获取say_hi
的返回值并将其打印出来,而不是从say_hi
函数本身打印。
这意味着您的函数需要返回您希望生成的整个字符串,并且您不能在该方法中使用模板标记。我会说限制单独违背了在erb模板中使用函数/方法的目的。
然而,如果render
是一个可以用来渲染不同的局部模板的函数,那将会很有趣......我只是把它看得很低而且看起来很render 'other_template.erb'
就像一个魅力!
所以考虑到这一点,我仍然建议坚持在配方中保持逻辑,只在模板中使用循环,条件和打印。我不确定在模板中使用render
的准则是什么,但我觉得不鼓励这样做。