2015-07-22 64 views
1

厨师是伟大的供应基本模板,但我期待将更多先进的模板逻辑。是这样的可能:定义厨师ERB模板方法

<% 
def say_hi() 
-%> 
    <%= "hi" %> 
<% 
end 
-%> 

# Extraneous template data here 

<% say_hi() -%> # Call to template method 

在这个例子中,我希望,每当say_hi()hi会产生,但它不工作。

这种行为是可能的,如果没有,有没有产生类似的行为方式?我假设厨师模板遵循通用的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

你试过了吗?输出是什么?什么是用例? (我真的不知道这可能会用在哪里)。由于对尝试目标的描述太少,因此不可能知道变量或部分模板是否可用。 – Tensibai

+0

我发现当他们开始拥有这么多的逻辑时,很难长期维护模板。当模板简单并且逻辑位于由配方调用的配方或库中时,阅读起来更容易。 – Martin

+0

该函数应该返回字符串,并且应该像'<%= say_hi %>'那样用'='输出函数的结果。但是在模板中使用逻辑和函数是一个坏主意。只需创建另一个模板并在配方中使用哪个模板即可使用。 –

回答

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的准则是什么,但我有一种感觉,它是不鼓励的。

+0

感谢您的回复!我也见过'render'使用过,但我不确定这是否会提供我正在寻找的功能。我编辑了我的问题,以包含更多相关背景,以了解我正在努力完成的任务。 –

+0

@JamesTaylor如果它只是YAML我通常只有一个名称空间的节点属性是该配置文件,然后我只是转储该散列使用'YAML ::转储(节点['mycookbook'] ['myconfig']。to_hash )'这通常是最简单的方式,对于最终用户来说很明显,他们可能已经拥有了应用程序配置文件的结构。 – edhurtig

+0

如果你走这条路线,你需要处理一些技巧......问题在于深度嵌套的节点属性。您需要将节点属性转换为JSON,然后返回到基本散列,然后转换为YAML ...疯狂,但效果很好 'YAML.dump(JSON.parse(node ['mycookbook'] ['myconfig']。to_hash .to_json))' – edhurtig