如果我理解正确,那么您真正的问题是,就插值而言,heredocs 的行为类似于双引号。因此,您所需要的只是一个行为类似于单引号的引用机制。 Ruby 有很多字符串引用机制,特别是我们有%q{...}
:
<% code = %q{
<div>
#{ image_tag 'image.png' }
</div>
} %>
如果您愿意,可以使用其他分隔符:%q|...|
, %q(...)
当然还是有变化,但至少你不用担心插值问题。
如果你确实想使用heredoc,你可以指定带引号的定界符终止符并且相应的引用样式将应用于内容:
<% code = <<'PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR'
<div>
#{ image_tag 'image.png' }
</div>
PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR
%>
中的单引号<<'PLACE...'
指定单引号规则(即无插值)适用于此处文档的内容。
当然,这些东西都不适用于嵌入式 ERB,如下所示:
<% code = %q{
<div>
<% ... %>
</div>
} %>
因为 ERB 解析器会看到第一个%>
作为外部的结束分隔符<% code...
部分。不用担心,我想我有一个计划,可以在不涉及严重黑客攻击或太多工作的情况下发挥作用。
一些预备知识:
- 导轨用途Erubis用于 ERB 处理。
- Erubis 让您能够更改分隔符:pattern option到它的构造函数。
- 导轨用途Tilt and 链轮处理模板处理管道,这些允许您做出正确的事情
pancakes.js.coffee.erb
以正确的顺序。
使用上面的内容,您可以添加自己的模板格式,即具有不同分隔符的 ERB,并且您可以让 Rails 使用这种新格式来处理您的“特殊”部分,然后正常的 ERB 处理会造成混乱。
首先你需要连接Tilt。如果你看一下lib/tilt/erb.rb
在你的 Tilt 安装中,你会看到 Erubis 的东西Tilt::ErubisTemplate
在底部。你应该能够子类化Tilt::ErubisTemplate
并提供一个prepare
覆盖添加,比如说,:pattern => '<!--% %-->'
选项和弃踢到超类。然后在 Rails 初始化程序中使用 Tilt 和 Sprockets 注册它,如下所示:
Tilt.register(Your::Template::Subclass, 'klerb') # "kl" for "kludge" :)
Rails.application.assets.register_engine('.klerb', Your::Template::Subclass)
现在您的应用程序应该能够处理.klerb
文件与<!--% ... %-->
作为模板分隔符。您还可以使用以下名称将您的 klerb 与 erb 链接起来pancakes.html.erb.klerb
文件将在 ERB 之前经过 klerb;这意味着像这样的模板(在一个名为whatever.html.erb.klerb
):
<!--% code = <<PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR
<div>
<% image_tag 'image.png' %>
</div>
PLACE_THE_EXAMPLE_CODE_BETWEEN_THESE_TWO_LINES_EXACTLY_AS_YOU_WANT_IT_TO_APPEAR
%-->
<!--%= "code = escape_the_erb_as_needed(%q{#{code}})" %-->
<% do_normal_erb_stuff %>
会做正确的事。
你需要一个帮助者来实现escape_the_erb_as_needed
当然是功能性;一些小实验应该可以帮助你弄清楚什么需要逃避以及以什么方式逃避。
所有这些可能看起来有点复杂,但实际上非常简单。我使用 Tilt 和 Sprockets 添加了自定义模板处理步骤,最终结果非常简单;弄清楚要做哪些简单的事情需要一些工作,但我已经为您完成了这项工作:
-
Tilt::Template
子类,你可以通过小猪支持来得到这个Tilt::ErubisTemplate
.
- 通过拨打电话注册 Tilt
Tilt.register
.
- 通过致电注册 Sprockets
Rails.application.assets.register_engine
.
- ...
- Profit.