2011-01-11 4 views
1

У меня есть что-то вроде этого:Rails: link_to метод

<p> 
    <b>Tags:</b> 
    <%if @post.tags.count > 0%> 
    <%= @post.tags.collect {|c| (link_to c.name, c)}.join(", ")%> 
    <%else%> 
    Does not have any tags. 
    <%end%> 
</p> 

Который дает мне

Tags: <a href="/tags/1">Java</a>, <a href="/tags/2">CSS</a> 

Вместо Java и CSS ссылки. Что мне не хватает?

ответ

6

Это потому, что строки в Rails 3 по умолчанию, не считается безопасным для HTML. См. this blog post.

Вы можете вручную пометить что-то, как сейф, позвонив .html_safe на него, что позволит сделать ваш код так:

<p> 
    <b>Tags:</b> 
    <%if @post.tags.count > 0%> 
    <%= @post.tags.collect {|c| (link_to c.name, c)}.join(", ").html_safe %> 
    <%else%> 
    Does not have any tags. 
    <%end%> 
</p> 

Но я бы рекомендовал делать это вместо:

<p> 
    <b>Tags:</b> 
    <% if @post.tags.count > 0%> 
    <% @post.tags.each_with_index do |tag, i| %> 
     <%= link_to h(tag.name), tag %><%= ', ' if i < @post.tags.size - 1 %> 
    <% end %> 
    <% else %> 
    Does not have any tags. 
    <%end%> 
</p> 
3

Я думаю, что html_safe - это то, что вы ищете! Таким образом, это решит проблему (@ post.tags.collect {| c | (link_to c.name, c)}. Join (",")). Html_safe

1

Я думаю, ваши имена тегов должны вводиться пользователем, верно?

В этом случае html_safe не является вашим первым выбором, так как он полностью доверяет пользователю. И ваш сайт столкнется с атаками XSS.

Лучшим выбором должен быть sanitize. Смотрите ссылку здесь: http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html

Как вы только хотите иметь ссылки, следующая строка делать то, что вы хотите:

<%= sanitize @post.tags.collect {|c| (link_to strip_links(c.name), c)}.join(", "), :tags => %w(a) %> 

Обратите внимание на использование strip_links(c.name), это удаляет все ссылки, которые вводятся пользователем.

Предположим, имена тегов являются: [ "Продукт", "привет", "до свидания"]

только с помощью .html_safe, следующее будет показано:

<a href="/tags/1">Product</a>, <a href="/tags/2"><strong>hi</strong></a>, <a href="/tags/3"><a href='bad_site.com'>bye</a></a> 

Но используя сочетание Sanitize с strip_links, следующий результат:

<a href="/tags/1">Product</a>, <a href="/tags/2">&lt;strong&gt;hi&lt;/strong&gt;</a>, <a href="/tags/3">bye</a> 

Или вы можете смешивать использование strip_tags с .html_safe:

<%= @post.tags.collect {|c| (link_to strip_tags(c.name), c)}.join(", ").html_safe %> 

Это просто удаляет все теги в c.name перед вызовом html_safe.

Я бы предложил (и вы, вероятно, уже сделали: D) удаление всех нежелательных тегов перед хранением в базе данных.

+0

Я бы на самом деле предлагал _not_ депиляцию тегов перед тем, как поместить пользовательский ввод в базу данных. Откуда вы знаете, где это будет показано? Возможно, он будет отправлен через HTML, но, возможно, он также будет отправлен через JSON API и отображен в приложении для iPhone.У каждого среды отображения есть уникальные соображения безопасности, и точка, в которой вы храните данные, не является временем для учета всего, что вы могли бы сделать с этими данными. –

+0

Да, я согласен с тем, что сохранение того, что пользователь действительно вводит в базу данных, имеет свои преимущества. Но для нормального использования пользователь должен ввести только имя тега. Нелепо показать облако тегов, где в большинстве тегов есть неожиданные HTML-теги внутри. Четкое облако тегов с настраиваемой функцией масштабирования должно быть лучше, вместо пользовательских символов 'strong',' em' или даже 'font'! Неважно, где вы показываете (iphone, настольное приложение или любое другое), вы просто не ожидаете, что пользователь будет вводить теги HTML для своего имени тега. – PeterWong