定义 Chef ERB 模板方法
Defining a Chef ERB template method
Chef 非常适合提供基本模板,但我希望合并更高级的模板逻辑。这样的事情可能吗:
<%
def say_hi()
-%>
<%= "hi" %>
<%
end
-%>
# Extraneous template data here
<% say_hi() -%> # Call to template method
在这个例子中,我希望每当调用 say_hi()
时都会生成 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 -%>
遗憾的是,如果只能return值而不直接输出到ERB模板,这个相对优雅的策略就失效了。
这不是推荐的设计模式。逻辑应该保留在食谱和资源中。也就是说,有可能哪一个是你问题的核心,什么是我最感兴趣的
<%
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
的 return 值并打印它,而不是从 say_hi
函数本身打印。
这意味着您的函数需要 return 您希望它生成的整个字符串,并且您不能在该方法中使用模板标签。我要说的是,限制本身就违背了在 erb 模板中使用 functions/methods 的目的。
但是,如果 render
是一个可以用来呈现不同部分模板的函数,那将会很有趣...魅力!
鉴于此,我仍然建议坚持在食谱中保留逻辑,并仅在模板中使用循环、条件和打印。我不确定在模板中使用 render
的指导方针是什么,但我觉得不鼓励这样做。
Chef 非常适合提供基本模板,但我希望合并更高级的模板逻辑。这样的事情可能吗:
<%
def say_hi()
-%>
<%= "hi" %>
<%
end
-%>
# Extraneous template data here
<% say_hi() -%> # Call to template method
在这个例子中,我希望每当调用 say_hi()
时都会生成 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 -%>
遗憾的是,如果只能return值而不直接输出到ERB模板,这个相对优雅的策略就失效了。
这不是推荐的设计模式。逻辑应该保留在食谱和资源中。也就是说,有可能哪一个是你问题的核心,什么是我最感兴趣的
<%
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
的 return 值并打印它,而不是从 say_hi
函数本身打印。
这意味着您的函数需要 return 您希望它生成的整个字符串,并且您不能在该方法中使用模板标签。我要说的是,限制本身就违背了在 erb 模板中使用 functions/methods 的目的。
但是,如果 render
是一个可以用来呈现不同部分模板的函数,那将会很有趣...魅力!
鉴于此,我仍然建议坚持在食谱中保留逻辑,并仅在模板中使用循环、条件和打印。我不确定在模板中使用 render
的指导方针是什么,但我觉得不鼓励这样做。