定义Chef ERB模板方法

时间:2015-07-22 04:40:37

标签: templates chef erb

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模板,那么这种相对优雅的策略就会中断。

1 个答案:

答案 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的准则是什么,但我觉得不鼓励这样做。