178

I have

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

and in my erb view:

<%= @str %>

What will display on the page is: <b>Hi</b> when what I really want is Hi. What's the ruby way to "interpret" a string as HTML markup?


Edit: the case where

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

If in my view I do

<%raw @str %>

The HTML source code is <span class=\"classname\">hello</span> where what I really want is <span class="classname">hello</span> (without the backslashes that were escaping the double quotes). What's the best way to "unescape" those double quotes?

lulalala
  • 17,572
  • 15
  • 110
  • 169
Tim
  • 6,079
  • 8
  • 35
  • 41
  • You might also consider using the %Q[] syntax for string escaping. e.g `%Q["quotation marks"] => "\"quotation marks\""` Source: http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals#The_.25_Notation Don't know if that helps. – kingsfoil Oct 23 '14 at 21:23

9 Answers9

364

UPDATE

For security reasons, it is recommended to use sanitize instead of html_safe.

<%= sanitize @str %>

What's happening is that, as a security measure, Rails is escaping your string for you because it might have malicious code embedded in it. But if you tell Rails that your string is html_safe, it'll pass it right through.

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

OR

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

Using raw works fine, but all it's doing is converting the string to a string, and then calling html_safe. When I know I have a string, I prefer calling html_safe directly, because it skips an unnecessary step and makes clearer what's going on. Details about string-escaping and XSS protection are in this Asciicast.

user664833
  • 18,397
  • 19
  • 91
  • 140
Jacob
  • 4,971
  • 1
  • 22
  • 18
22

Use raw:

<%=raw @str >

But as @jmort253 correctly says, consider where the HTML really belongs.

ronan_mac
  • 428
  • 7
  • 16
Michael Stum
  • 177,530
  • 117
  • 400
  • 535
19

If you're on rails which utilizes Erubis — the shortest way to do it is

<%== @str >

Note the double equal sign. See related question on SO for more info.

jibiel
  • 8,175
  • 7
  • 51
  • 74
8

You can also use simple_format(@str) which removes malicious code. Read more here: http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#method-i-simple_format

bcackerman
  • 1,486
  • 2
  • 22
  • 36
7

Or you can try CGI.unescapeHTML method.

CGI.unescapeHTML "&lt;p&gt;This is a Paragraph.&lt;/p&gt;"
=> "<p>This is a Paragraph.</p>"
Arman Ortega
  • 3,003
  • 1
  • 30
  • 28
7

You are mixing your business logic with your content. Instead, I'd recommend sending the data to your page and then using something like JQuery to place the data where you need it to go.

This has the advantage of keeping all your HTML in the HTML pages where it belongs so your web designers can modify the HTML later without having to pour through server side code.

Or if you're not wanting to use JavaScript, you could try this:

@str = "Hi"

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

At least this way your HTML is in the HTML page where it belongs.

jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
  • The problem is, my app is taking in a file that is poorly marked up, and "translating" it via regexes to good HTML markup to send to the view. Therefore, the HTML markup that is being generated is dynamic, so I can't know a priori which tags that are supposed to surround @str. Where would I perform this "translation" work, if not in the models? I thought we weren't supposed to have extensive logic code in the views. – Tim Jan 02 '11 at 03:22
  • 1
    It's really a matter of opinion. When developing a fresh app I prefer to keep everything as clean as possible. But oftentimes we must work within the constraints of what others have left us with. If your datasource returns HTML markup then perhaps take a look at using "raw" as described in Michael Stum's solution. – jamesmortensen Jan 02 '11 at 03:29
  • 1
    If you have inherited support of some code, and the code has areas that show poor thinking or design, then it really is part of your responsibility to clean it up to make it more maintainable. Leaving it as you found it is fine when it's great code to begin with, but leaving it better than you found it is good when it needed work. Part of my job is managing some legacy apps; I'm a fan of not fixing things that are not broken, but they couldn't be enhanced easily because of how they were written. I had to rewrite most of the function calls but it's SO much easier to work with now. – the Tin Man Jan 02 '11 at 09:03
  • You shouldn't be using JavaScript for your HTML interpolation if there's no other reason to use JS. That will break your site for non-JS browsers (yes, there *are* some). – Marnen Laibow-Koser Nov 11 '11 at 21:03
  • The html belongs in helpers too, and good forbids, in the database sometimes. Although I much rather storing markdown and then rendering to html. – Macario Jun 28 '12 at 17:06
  • @Macario - Hi, I'm not sure I fully understand your comment. Do you mind elaborating? Thank you! – jamesmortensen Jun 28 '12 at 17:39
  • Well sometimes html is generated outside the template in a helper function an needs not to be escaped, or sometimes, -allthough in my opinion is a bad practice and not pretty- it is generated by the user by a WYSIWG editor and stored in the database as html and also needs not to be escaped, off course it would need to be sanitized or bad things can happen. I prefer the templating language Markdown for letting the user input styled content. In that case you don't want your content to be escaped `<%= str.html_safe %>` is the way. – Macario Jun 28 '12 at 21:22
  • 1
    Off course if you allow non escaped content the resposabitily of ensuring non evil markup is up to you. – Macario Jun 28 '12 at 21:31
0

@str = "<span class=\"classname\">hello</span>" If in my view I do

<%raw @str %> The HTML source code is <span class=\"classname\">hello</span> where what I really want is <span class="classname">hello</span> (without the backslashes that were escaping the double >quotes). What's the best way to "unescape" those double quotes?

Solution: use double quotes inside of single quotes (or single inside of double) to avoid escaping with a backslash.

@str = '<span class="classname">hello</span>'
<%raw @str %>
Crash
  • 321
  • 1
  • 4
  • 15
0

The html_safe version works well in Rails 4...

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

since you are translating, and picking out your wanted code from a person's crappy coded file, could you use content_tag, in combo with your regex's.

Stealing from the api docs, you could interpolate this translated code into a content_tag like:

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

Not knowing your code, this kind of thinking will make sure your translated code is too compliant.

pjammer
  • 9,489
  • 5
  • 46
  • 56
  • I'm assuming translated_text is the actual content within the div, right? ie, in the example, it'd be "Hello world!"? What if translated_text has more HTML in it, ie nested divs or spans? Would I have to call content_tag many times then? – Tim Jan 02 '11 at 04:11
  • and... sorry hit enter early... each nested div/span inside is still a content_tag and you still need to validate it though right? Since we can't see what you are doing with your fancy translating ;-), I'd assume you look for ALL tags, regardless if the regex is on the 'parent' of the html... such as
      . you wouldn't put all li's as a big ass string to print would you? each one would be it's own content_tag :li, text correct?
    – pjammer Jan 02 '11 at 15:00