在ERB块中的字符串内包括ERB分隔符 [英] Include ERB delimiters inside of a string in an ERB block

查看:86
本文介绍了在ERB块中的字符串内包括ERB分隔符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究样式指南,该指南显示代码以及输出。它目前的结构使得该代码仅需描述一次,并以其原始版本和解释版本显示,例如:

 <%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
%>

<%=原始代码%>
<%= content_tag:pre,code,class: prettyprint linenums%>

这很棒,而且相当容易维护。问题来自于Rails助手,例如上例中的 image_tag 。视图示例正确显示了div中的图像,而代码示例显示了相关的HTML。在这种情况下,相关的HTML包括一个定位标记- image_tag 方法的结果,而不是调用本身。



<我希望代码示例显示帮助程序方法,而不是它们的结果。我可以通过在文件中指定示例代码,然后渲染或读取文件来完成这项工作。我希望通过如上所述在变量中指定代码来完成这项工作,但似乎无法使ERB分隔符在erb块内的字符串内工作。即使是最简单的<%foo =‘<%= bar%>’%> 的情况也无法使用。我试过使用语法(例如< %% %%> %%),使用官方文档中的详细信息成功。



我可以找到的唯一信息是 ,使用<%=< +%=%> link_to<%= image.css_tag.humanize%> <%=% +> %> %> ,在这种情况下不起作用(如果有的话)。



因此,有一种方法可以指定字符串包含在ERB字符串中的ERB结束定界符(%> ),还是我使用了稍微笨拙的文件读取方法?谢谢!



编辑:



我最终想得到的是一个有效的版本:

 <%#理想代码-不起作用%> 
<%代码=<< 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
%>

因此<%=原始代码%> 将(继续)输出:

 < div> 
< img src = / images / image.png alt =图片 />
< / div>

并且<%= content_tag:pre,code,class: prettyprint linenums%> 将输出:

 < pre class = prettyprint linenums> 
< div>
<%image_tag‘image.png’%>
< / div>
< / pre>

不是使用变量时的当前操作,而是:

 < pre class = prettyprint linenums> 
< div>
< img src = / images / image.png alt = Image />
< / div>
< / pre>

我希望用户能够复制代码示例并将其粘贴到新视图中,而不必将HTML转换回产生它们的助手。我认为我基本上需要的是替代的ERB分隔符,就像' (甚至是%q {} )因字符串而异,即使最后的ERB分隔符出现在字符串内部,实际上也被当作块的末尾处理。 <%foo ='<%= bar%>'%> 最简单的情况说明了我要完成的工作。在生成器中,您可以使用<%foo ='< %% = bar%>'%> (或类似的东西),告诉它不要在那时和那里都作为ERB处理。从文件或什至在纯rb文件(例如辅助文件)中读取时,所有这些都可以正常工作,但是在这种情况下,将其放在视图中是最有意义的,因为我们希望可以轻松地对其进行操作。设计师。

解决方案

如果我理解的正确,那么您真正的问题是,就插值而言,heredocs的行为就像双引号一样因此,您需要的是报价g行为类似于单引号的机制。 Ruby有很多字符串引用机制,特别是我们有%q {...}

 <%代码=%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 ...'指定将单引号规则(即无插值)应用于heredoc的内容。






当然这些东西都不能与嵌入式ERB一起使用:

 <%code =%q {
< div>
<%...%>
< / div>
}%>

因为ERB解析器将看到第一个%> 作为外部<%code ... 部分的结束定界符。不用担心,我认为我的计划可以在不涉及大量黑客入侵或过多工作的情况下起作用。



一些预备赛




  • Rails使用 Erubis 用于ERB处理。

  • Erubis允许您使用:pattern 选项将定界符更改为其构造函数。

  • Rails使用< a href = https://github.com/rtomayko/tilt rel = nofollow>倾斜和 Sprockets 来处理模板处理管道,它们使您可以按正确的顺序对 pancakes.js.coffee.erb 进行正确的处理。



使用上面的代码,您可以添加自己的模板格式,即带有不同分隔符的ERB,Rails可以使用这种新格式来处理您的模板 spe正常的ERB处理之前的社交部分)会造成混乱。



首先,您需要连接Tilt。如果您在Tilt安装中查看 lib / tilt / erb.rb ,您会在 Tilt :: ErubisTemplate <中看到Erubis内容。 / code>在底部。您应该可以将 Tilt :: ErubisTemplate 子类化,并提供 prepare 替代,例如,添加:pattern => ’<!-%%->’选项,然后进入超类。然后使用以下代码在Rails初始化程序中使用Tilt和Sprockets进行注册:

  Tilt.register(Your :: Template ::子类,'klerb')# kl表示 kludge :) 
Rails.application.assets.register_engine('。klerb',Your :: Template :: Subclass)

现在您的应用程序应该能够使用 .klerb 文件><!-%...%-> 作为模板定界符。您还可以使用 pancakes.html.erb.klerb 之类的名称将klerb与erb链接,并且文件将在ERRB之前通过klerb;这意味着像这样的模板(在名为 whatever.html.erb.klerb 的文件中):

 <!-%代码=<< 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
%->
<!-%=代码= escape_the_erb_as_needed(%q {#{code}})%->
<%do_normal_erb_stuff%>

会做正确的事。



当然,您需要一个帮助程序来实现 escape_the_erb_as_needed 功能。稍作试验就可以帮助您找出需要逃脱的内容以及以何种方式逃脱。



所有这些可能看起来有些复杂,但确实非常简单。我已经添加了使用Tilt和Sprockets进行自定义模板处理的步骤,最终结果非常简单;弄清楚要做哪些简单的事情需要花费一些工作,但我已经为您完成了这项工作:


  1. 倾斜:: Template 子类,您可以通过在 Tilt :: ErubisTemplate 上小猪支持。

  2. 注册通过调用 Tilt.register 倾斜。$ li
  3. 通过调用 Rails.application.assets.register_engine <向Sprockets注册。 / code>。

  4. ...

  5. 利润。


I am working on a style guide which displays the code, as well as the output. It is currently structured so that the code only needs to be described once, and is displayed in both its raw and interpreted versions, like so:

<% 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
%>

<%= raw code %>
<%= content_tag :pre, code, class: "prettyprint linenums" %>

This is great, and fairly easy to maintain. The problem comes in with the rails helpers, like image_tag in the above example. The view example correctly displays an image in a div, and the code example displays the relevant HTML. In this case, the relevant HTML includes an anchor tag - the results of the image_tag method, not the call itself.

I would prefer the code examples to display the helper methods, rather that their results. I am able to make this work by specifying the example code in a file, and either rendering or reading the file. I would prefer to make this work by specifying the code in a variable, as above, but I can't seem to get an ERB delimiter to work inside of a string inside of an erb block. Even the simplest case of <% foo = '<%= bar %>' %> doesn't work at all. I've tried playing with the syntax (<%% %%> and % % for example), using details from the official documentation, without much success.

The only information I could find on the matter is here, using <%= "<" + "%=" %> link_to <%= image.css_tag.humanize %> <%= "%" + ">" %> %>, which does not work in this use case (if at all).

So, is there a way to specify a string that contains a ERB end-delimiter (%>) in an ERB string, or am I stuck using the slightly clunkier file-read method? Thanks!

Edit:

What I would like to end up with is a working version of this:

<%# Idealized code - does not work %>
<% 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
%>

So that <%= raw code %> would (continue to) output:

<div>
  <img src="/images/image.png" alt="Image" />
</div>

And <%= content_tag :pre, code, class: "prettyprint linenums" %> would output:

<pre class="prettyprint linenums">
  <div>
    <% image_tag 'image.png' %>
  </div>  
</pre>

Instead of what it currently does when using a variable, which is:

<pre class="prettyprint linenums">
  <div>
    <img src="/images/image.png" alt="Image" />
  </div>
</pre>

I want users to be able to copy the code example and paste it into a new view, without having to translate HTML back into the helpers that produce them. I think what I basically need is an alternative ERB delimiter, in the same way that ' and " (or even %q{}) vary for strings. It seems that even though the final ERB delimiter is occurring inside of a string, it is being actually processed as the end of the block. The simplest case of <% foo = '<%= bar %>' %> demonstrates somewhat what I want to accomplish. In a generator, you might use <% foo = '<%%= bar %>' %> (or something similar), to tell it not to process as ERB right then and there. This all works fine when reading from a file, or even in a pure rb file (like a helper), but it makes the most sense to put it in the view, in this case, as it is intended to be easily manipulated by our designers.

解决方案

If I'm understanding you right, your real problem is that heredocs behave like double quotes as far as interpolation is concerned. So all you need is a quoting mechanism that behaves like single quotes. Ruby has lots of string quoting mechanisms, in particular we have %q{...}:

<% code = %q{
<div>
  #{ image_tag 'image.png' }
</div>  
} %>

You can use other delimiters if you'd like: %q|...|, %q(...), etc. There's still a change of course but at least you don't have to worry about interpolation problems.

If you really want to use a heredoc, you can specify the heredoc terminator with quotes and the corresponding quoting style will apply to the content:

<% 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
%>

The single quotes in <<'PLACE...' specify that single quoting rules (i.e. no interpolation) apply to the heredoc's content.


Of course none of that stuff will work with embedded ERB like this:

<% code = %q{
<div>
  <% ... %>
</div>  
} %>

because the ERB parser will see the first %> as the closing delimiter for the outer <% code... part. Fear not, I think I have a plan that will work without involving gross hacks or too much work.

Some preliminaries:

Using the above you can add your own template format that is ERB with a different delimiter and you can have Rails use this new format to handle your "special" sections before the normal ERB processing can make a mess of things.

First you need to hook up Tilt. If you have a look at lib/tilt/erb.rb in your Tilt installation, you'll see the Erubis stuff in Tilt::ErubisTemplate at the bottom. You should be able to subclass Tilt::ErubisTemplate and provide a prepare override that adds, say, a :pattern => '<!--% %-->' option and punts to the superclass. Then register this with Tilt and Sprockets in a Rails initializer with something like this:

Tilt.register(Your::Template::Subclass, 'klerb') # "kl" for "kludge" :)
Rails.application.assets.register_engine('.klerb', Your::Template::Subclass)

Now your application should be able to handle .klerb files with <!--% ... %--> as the template delimiters. And you can also chain your klerb with erb using names like pancakes.html.erb.klerb and the file will go through klerb before the ERB; this means that templates like this (in a file called 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 %>

will do The Right Thing.

You'd need a helper to implement the escape_the_erb_as_needed functionality of course; a little experimentation should help you sort out what needs to be escape and in what way.

All that might look a bit complicated but it is really pretty straight forward. I've added custom template processing steps using Tilt and Sprockets and it turned out to be pretty simple in the end; figuring out which simple things to do took some work but I've already done that work for you:

  1. Tilt::Template subclass, you get this by piggy backing on Tilt::ErubisTemplate.
  2. Register with Tilt by calling Tilt.register.
  3. Register with Sprockets by calling Rails.application.assets.register_engine.
  4. ...
  5. Profit.

这篇关于在ERB块中的字符串内包括ERB分隔符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆