Ruby on Rails:如何将字符串呈现为HTML?

179

我有

@str = "<b>Hi</b>"

而在我的 erb 视图中:

<%= @str %>

当我想要显示的是 Hi,但实际上页面上显示的是 <b>Hi</b>。在 Ruby 中,如何将一个字符串“解释”为 HTML 标记?

@str = "<span class=\"classname\">hello</span>"

如果在我的视角中,我执行

<%raw @str %>

HTML源代码是<span class=\"classname\">hello</span>,但我真正想要的是<span class="classname">hello</span>(没有转义双引号的反斜杠)。最好的方法是“取消转义”这些双引号?


你也可以考虑使用%Q[]语法进行字符串转义。 例如%Q["引号"] => "\"引号\""来源:http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals#The_.25_Notation不知道这是否有帮助。 - kingsfoil
9个回答

365

更新

出于安全原因,建议使用sanitize替代html_safe

<%= sanitize @str %>

Rails是在进行安全保护,防止字符串中嵌入恶意代码。因此,它会对字符串进行转义。但是如果你告诉Rails你的字符串是html_safe的,它就不会再转义了。

@str = "<b>Hi</b>".html_safe
<%= @str %>

或者

@str = "<b>Hi</b>"
<%= @str.html_safe %>

使用raw是可以的,但它只是将字符串转换为另一个字符串然后再调用html_safe。当我知道我有一个字符串时,我更喜欢直接调用html_safe,因为它跳过了一个不必要的步骤,并且更清晰地说明了正在发生的事情。有关字符串转义和XSS保护的详细信息,请参见此Asciicast


1
太棒了。我搜索了一个小时也找不到如何做到这一点。感谢您的回答。 - Salil
1
我一直使用raw。很高兴知道这个! - jmcharnes
来自未来的感谢 =) - Carlos Morales
2
根据 https://dev59.com/glcP5IYBdhLWcg3wVYeh,sanitize 已被移除。 - Youness

23

使用raw函数:

<%=raw @str >

但正如 @jmort253 正确所说,考虑 HTML 真正的归属位置。


嗨,这个解决方案有效,但有一个注意事项:请参见编辑后的问题。 - Tim

19
如果您使用的是使用Erubisrails,最简单的方法是:
<%== @str >

请注意双等号。查看相关的SO问题以获取更多信息。

8

7
你正在将业务逻辑与内容混合在一起。相反,我建议将数据发送到页面,然后使用类似于 JQuery 的工具将数据放置到需要的位置。
这样做的好处是将所有 HTML 嵌入到 HTML 页面中,使得网页设计师能够修改 HTML 而不必查看服务器端代码。
或者,如果你不想使用 JavaScript,可以尝试以下方法:
@str = "Hi"

<b><%= @str ></b>

至少这样你的HTML就在它应该在的HTML页面中了。


1
这实际上是一个观点问题。在开发新应用程序时,我更喜欢尽可能保持整洁。但往往我们必须在别人留给我们的限制内工作。如果您的数据源返回HTML标记,则可以考虑使用Michael Stum解决方案中描述的“raw”。 - jamesmortensen
1
如果你继承了一些代码的支持,并且这些代码存在一些显示出糟糕思考或设计的区域,那么将其清理以使其更易于维护确实是你的责任之一。当它本来就是很好的代码时,按原样保留它是可以的,但当它需要工作时,让它比你发现时更好是很好的。我的工作之一是管理一些遗留应用程序;我不喜欢修复没有问题的东西,但由于它们的编写方式,它们无法轻松地进行增强。我不得不重写大部分函数调用,但现在使用起来要容易得多。 - the Tin Man
如果没有其他使用JS的原因,您不应该在HTML插值中使用JavaScript。这将破坏非JS浏览器(是的,有一些)的站点。 - Marnen Laibow-Koser
HTML 也应该放在 helpers 中,但是最好不要存储在数据库中。虽然我更喜欢存储 Markdown 然后再渲染成 HTML。 - Macario
1
当然,如果您允许非转义内容,则确保非恶意标记的责任就在您身上。 - Macario
显示剩余3条评论

7

或者您可以尝试使用CGI.unescapeHTML方法。

CGI.unescapeHTML "&lt;p&gt;This is a Paragraph.&lt;/p&gt;"
=> "<p>This is a Paragraph.</p>"

0

@str = "<span class=\"classname\">hello</span>" 如果我在视图中执行以下操作:

<%raw @str %> HTML源代码是<span class=\"classname\">hello</span>,但我真正想要的是<span class="classname">hello</span>(没有转义双引号的反斜杠)。最好的方法是什么来“取消转义”这些双引号?

解决方案:在单引号内使用双引号(或在双引号内使用单引号),以避免使用反斜杠进行转义。

@str = '<span class="classname">hello</span>'
<%raw @str %>

0

html_safe 版本在 Rails 4 中工作得很好...

<%= "<center style=\"color: green; font-size: 1.1em\" > Administrators only </center>".html_safe if current_user.admin? %
>

0

既然你正在翻译并从某人的烂代码文件中挑选你想要的代码,那么你能否使用content_tag与正则表达式结合起来呢?

从API文档中借鉴,你可以将这段翻译后的代码插入到content_tag中,如下:

<%= content_tag translated_tag_type.to_sym, :class => "#{translated_class}" do -%>
<%= translated_text %>
<% end -%>
# => <div class="strong">Hello world!</div>

不了解你的代码,这种思维方式会确保你翻译的代码过于符合规范。


我假设translated_text是div内的实际内容,对吗?即,在这个例子中,它将是“Hello world!”?如果translated_text中有更多的HTML,比如嵌套的div或span,那我是否需要多次调用content_tag? - Tim
每个嵌套的div/span内部仍然是一个content_tag,你仍然需要验证它,对吧?由于我们看不到你使用 fancy translating 的方式,我假设你会查找所有标签,而不管正则表达式是否在html的“父级”上...比如<ul>。你不会把所有的li都放在一个大字符串中打印出来,对吧?每个li都应该是自己的content_tag :li,文本正确吗? - pjammer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接