我有一个用户可以上传的模板,可以生成报告。他们可以将特殊标签放入html模板中,它将替换为db中的数据。快速举例:
<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会是什么。
答案 0 :(得分:1)
我对此也很好奇,发现了一个非常类似的讨论here。老实说,我认为这取决于解析代码的数量。如果只有很少的线,那么模型是一个安全的地方。如果它将是一个大包,特别是一个可重用的包,/ lib /文件夹可能是解析本身更好的选择。但是,您肯定应该如您所建议的那样将其从控制器中删除。
答案 1 :(得分:0)
我同意逻辑不应该在控制器中,但让我们得到一个 更具体地说明你将如何实现这一目标。
首先,您将模板存储在数据库中的哪个位置?他们
应该存储在他们自己的模型中,让我们称之为
CustomerTemplate
并提供属性:Text类型的模板。
所以现在我们有两种类型的对象,Customer和
CustomerTemplates。如何为客户提供模板?它
老实说,只有一个render
功能才能可怕
CustomerTemplate模型,它接受客户并呈现它,但是
它在您的应用程序中放置了一些不严格属于的逻辑
那里。你应该把“客户特定的渲染逻辑”分开
来自“渲染我简单的自定义模板语言”。
那么,让我们为您的自定义语言创建一个简单的模板处理程序, 我要昵称 Curly 。这个处理程序应该一无所知 顾客。它所做的只是取一个字符串并在其中插入值 {}的。这样,如果您希望将来添加新的模板类型 - 比如说,要像发票那样渲染另一个模型 - 你也可以使用相同的模型 模板类型。
Rails中的模板是响应call
的类
在ActionView::Template注册。最简单的例子是Builder。
这是一个快速编写的模板处理程序,它呈现了Curly。该
call
函数返回一个eval'd的字符串,所以字符串必须
是有效的红宝石代码。由render调用确定的字符串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 }) %>
不要在生产中使用我的示例代码!我遗漏了一堆角落 您需要处理的案例,例如清理用户输入。