我同意邏輯不應該在控制器中,但讓我們更具體地瞭解一下你如何實現這一點。
首先,您將模板存儲在數據庫中?他們 應該存儲在他們自己的模型中,我們稱之爲 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 }) %>
沒有使用我的示例代碼在生產中!我忽略了一大堆你需要處理的案例,如清理用戶輸入。
'lib'文件夾是你需要把它。這不是'model'代碼,因爲你沒有將它存儲在數據庫中。 (lib的另一種選擇是創建一個'app/services'文件夾,它也適用於這種情況) –
我假設它將在客戶模型中進行,而不是它將是它自己的模型。例如: def self.parse(html) –
客戶模型將不是正確的地方。什麼更有意義:'customer.parse_template'或'customer.address'?在客戶模型中被解析的模板違反了單一職責原則,並且(如前所述)最好移動到「服務」或「庫」對象中。 –