2015-07-22 115 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