2013-07-11 27 views
3

我有一個用戶可以上傳的模板來生成報告。他們可以將特殊標籤放入html模板中,並用db中的數據替換。快速示例:如何在RoR中構建Util類

<div class="customer-info"> 
    <h1>{customer_name}</h1> 
    <h2>{customer_address_line1}</h2> 
    <h2>{customer_address_line2}</h2> 
    <h2>{customer_address_city}, {customer_address_state} {customer_address_zip}</h2> 
</div> 

我有一個控制器,它查找客戶然後解析模板並替換標記。

現在我在控制器中創建一個胖控制器的解析代碼。不好。

但我應該在哪裏移動代碼?型號文件夾?創建一個Util文件夾並把它放在那裏?

只是不確定Rails Way會是什麼。

回答

1

我也很好奇,發現了一個非常類似的討論here。老實說,我認爲這取決於有多少解析代碼。如果只有幾條線,那麼該模型是一個安全的地方。如果它將是一個大包,尤其是可重用的包,那麼/ lib /文件夾可能是解析本身的更好選擇。但是,您應該按照您的建議將其從控制器中移除。

+1

'lib'文件夾是你需要把它。這不是'model'代碼,因爲你沒有將它存儲在數據庫中。 (lib的另一種選擇是創建一個'app/services'文件夾,它也適用於這種情況) –

+0

我假設它將在客戶模型中進行,而不是它將是它自己的模型。例如: def self.parse(html) –

+0

客戶模型將不是正確的地方。什麼更有意義:'customer.parse_template'或'customer.address'?在客戶模型中被解析的模板違反了單一職責原則,並且(如前所述)最好移動到「服務」或「庫」對象中。 –

0

我同意邏輯不應該在控制器中,但讓我們更具體地瞭解一下你如何實現這一點。

首先,您將模板存儲在數據庫中?他們 應該存儲在他們自己的模型中,我們稱之爲 CustomerTemplate並給出一個屬性:Text類型的模板。

所以現在我們有兩種類型的對象Customers和 CustomerTemplates。如何呈現給定模板的客戶?它 老老實實不會可怕只是有一個render功能 的CustomerTemplate模型,需要一個客戶並對其進行渲染,但 它是把一些邏輯您的應用程序不嚴格屬於 有內部。您應該從「渲染我的簡單自定義模板語言」中分離出「客戶特定的渲染邏輯」 。

所以,讓我們爲您定製的語言, 這我要暱稱捲毛一個簡單的模板處理程序。這位經理應該對 客戶一無所知。它所做的只是在 {}的內部採用一個字符串並插值。這樣,如果您希望將來添加新的模板類型 - 說,要呈現另一個模型(如發票),則可以使用相同的 模板類型。 Rails中

模板是其中call迴應並 與ActionView::Template註冊類。最簡單的例子是Builder

這是一個快速編寫的模板處理程序,呈現Curly。 call函數返回一個被評估的字符串,所以字符串必須爲 爲有效的ruby代碼。字符串eval在渲染調用的範圍內,因此 它可以訪問通過{ locals: {} } 選項傳入的任何變量以進行渲染。

# In lib/curly_template_handler.rb 
class CurlyTemplateHandler 
    def self.call(template) 
    src = template.source 
    """ 
    r = '#{src}'.gsub(/{([^}]*)}/) { |s| 
     local_assigns[$1.to_sym] || s 
    } 
    raw r 
""" 
    end 
end 

確保處理程序初始化,讓我們將它設置爲監聽 的:花型。

# In config/initializers/register_curly_template.rb 
ActionView::Template.register_template_handler(:curly, CurlyTemplateHandler) 

我們需要添加的lib /到autoload_paths所以類加載:

# config/application.rb 
config.autoload_paths += %W(#{config.root}/lib) 

最後,我們可以使我們的模板,我們認爲!我在這裏嵌入字符串,但你真的從CustomerTemplate對象得到它:

<%= render(inline: "<h2>{customer_name}</h2><p>{customer_address}</p>", 
      type: :curly, 
      locals: { customer_name: @customer.name, 
      customer_address: @customer.address }) %> 

沒有使用我的示例代碼在生產中!我忽略了一大堆你需要處理的案例,如清理用戶輸入。