Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3.0.2 Array#join HTML Safe?

I have a rails gem that uses a snippet like:

components = []
components << label_for(attribute)
components << ...
components << text_field(attribute)
return components.join

The gem worked fine in Rails 3.0.1, however it escapes (renders as text in a browser) all HTML after updating to Rails 3.0.2. What am I doing something wrong? Thanks.

like image 349
Kevin Sylvestre Avatar asked Nov 16 '10 03:11

Kevin Sylvestre


4 Answers

As @sj26 points out, either use the rails built-in helper:

<%= safe_join(components) %>

Or use my rails_join gem to make Array#join html-safe aware, in which case your original code will work as is.

like image 164
Marc-André Lafortune Avatar answered Nov 12 '22 21:11

Marc-André Lafortune


String#join isn't SafeBuffer-aware.

String#html_safe marks that you string is already HTML-escaped, preventing users sneaking bits of HTML into your pages. Check out this post by Yehuda Katz on SafeBuffer and why/how you should be using them.

If you have an array of String and SafeBuffer you want to concatenate, make sure you've run #html_safe on them all, or #concat them into a SafeBuffer like so:

['<one>', '<p>two</p>'.html_safe].inject ''.html_safe, &:concat
=> "&lt;one&gt;<p>two</p>" 

Rails has a built-in helper called safe_join which will do this for you.

like image 35
sj26 Avatar answered Nov 12 '22 20:11

sj26


http://makandra.com/notes/954-don-t-mix-array-join-and-string-html_safe

class Array
  def html_safe_join(delimiter='')
    ''.html_safe.tap do |str|
      each_with_index do |element, i|
        str << delimiter if i > 0
        str << element
      end
    end
  end
end
[safe_string, unsafe_string].html_safe_join(' ') 
# '<span>foo</span>&lt;span&t;bar&lt;/span&gt;'
like image 2
grosser Avatar answered Nov 12 '22 21:11

grosser


Strings are automatically HTML-escaped in Rails3. You need to change that last line to:

return components.join.html_safe

alternately, if editing the gem is too much hassle you can do it from the view:

<%= helper_name.html_safe %>
like image 1
Adam Lassek Avatar answered Nov 12 '22 21:11

Adam Lassek