2

I'm having difficulties with my output not being encoded even though I'm using raw or html_safe.

This one is writing out the &nbsp in my final HTML page.

def build_tag_cloud(tag_cloud, style_list)
    tag_cloud.sort!{ |x,y| x.permalink <=> y.permalink }
    max, min = 0, 0
    tag_cloud.each do |tag|
        max = tag.followers.to_i if tag.followers.to_i > max
        min = tag.followers.to_i if tag.followers.to_i < min
    end

    divisor = ((max - min) / style_list.size) + 1

    html = ""
    tag_cloud.each do |tag|
        name = raw(tag.name.gsub('&','&amp;').gsub(' ','&nbsp;'))
        link = raw(link_to "#{name}", {:controller => "/shows", :action => "show", :permalink => tag.permalink}, :class => "#{style_list[(tag.followers.to_i - min) / divisor]}")
        html += raw("<li>#{link}</li> ")
    end
    return raw(html.to_s)
end

What is allowed in using raw and html_safe? And how can my example above be fixed?

Jeroen
  • 1,168
  • 1
  • 12
  • 24
Frexuz
  • 4,732
  • 2
  • 37
  • 54
  • I have noticed that as well, but found no reason, why it did not work. I am not sure if it is "allowed" to use `raw` or `html_safe` multiple times on strings, and what happens, if you add something to a "safe" string. – mliebelt Oct 29 '11 at 12:41

2 Answers2

3

What class is this code from? The raw method is declared on a helper, so it can only be used on controllers and views.

Source: raw vs. html_safe vs. h to unescape html

Also, unless this method is on a view page (which would just be poor implementation of Rails' MVC), you can't use the link_to function. That helper is only available on views. Also, you shouldn't need to call raw repeatedly in this function. I would think that you could just do this:

def build_tag_cloud(tag_cloud, style_list)
  ...
  html = ""
  tag_cloud.each do |tag|
    name = tag.name.gsub('&','&amp;').gsub(' ','&nbsp;')
    html += "<a href='#{shows_show_path(tag.permalink)}' class='#{style_list[(tag.followers.to_i - min) / divisor]}'>#{name}</a>"
  end
  html.html_safe
end
Community
  • 1
  • 1
Batkins
  • 5,547
  • 1
  • 28
  • 27
  • build_tag_cloud is a helper. And I've also tried to do raw/html_safe at the end (as your html.html_safe). The repeated raw is just to try to locate where to put it. – Frexuz Nov 09 '11 at 18:04
  • So which class is the `build_tag_cloud` method on? ApplicationController or a helper file? Did you try my code to see if it works? – Batkins Nov 09 '11 at 20:22
  • Ok, so it works if doing the a-tag as a string, instead of using the link_to method. Though I find it very ugly code. Why can't I make the link_to html_safe ?! – Frexuz Nov 11 '11 at 21:26
  • Not sure. I was actually a little surprised to find that link_to works inside of helpers as I was under the impression that it only worked on view classes. I'm guessing that the html_safe executes on the strings in the helper class, but that the link_to helper doesn't get converted to a string until it reaches the view. Perhaps you could just put the .html_safe on the view code where it is rendering the attribute and it might work then? – Batkins Nov 12 '11 at 00:02
  • I'm actually already doing that. <%= raw(build_tag_cloud(@tags, %w(tag1 tag2 tag3 tag4 tag5 tag6 tag7 tag8 tag9 tag10))) %>. And about the helpers; they have the full context of the view. Essentially, link_to is a helper too :) – Frexuz Nov 12 '11 at 00:43
  • Frexuz, I actually ran into a similar situation last night where I was writing a helper method to render some html on the view, and ended up seeing some of it not render properly. The issue was that the content I was feeding into the `link_to` tag was being escaped by rails after the `html_safe` executed (or it was being ignored as escapable code). I'm guessing you had a situation where the `name` attribute had `&nbsp`. Try this: `link_to(name.html_safe, {:controller => "/shows", :action => "show", :permalink => tag.permalink}, :class => "#{style_list[(tag.followers.to_i - min) / divisor]}")` – Batkins Nov 16 '11 at 16:34
1

The raw and html_safe methods both specifically tell rails not to escape your output (raw is preferred, and obviates the explicit to_s).

raw Reference
html_safe Reference

I suspect the reason you are using raw is because of the li tags. I would recommend using a content tag helper for those. Then you shouldn't need to mess around with encoding at all. You may need to put the link_to method directly into the content_for :li for the link to work properly (I would try without first).

content_tag Reference

Brad Werth
  • 17,411
  • 10
  • 63
  • 88
  • Using content_tag did not work for me. html += content_tag(:li, link_to("#{name}", some_path, :class => "some_class")) – Frexuz Nov 11 '11 at 21:30