Asked  7 Months ago    Answers:  5   Viewed   43 times

Suppose I have the following string

@x = "<a href='#'>Turn me into a link</a>"

In my view, I want a link to be displayed. That is, I don't want everything in @x to be unescaped and displayed as a string. What's the difference between using

<%= raw @x %>
<%= h @x %>
<%= @x.html_safe %>

?

 Answers

88

Considering Rails 3:

html_safe actually "sets the string" as HTML Safe (it's a little more complicated than that, but it's basically it). This way, you can return HTML Safe strings from helpers or models at will.

h can only be used from within a controller or view, since it's from a helper. It will force the output to be escaped. It's not really deprecated, but you most likely won't use it anymore: the only usage is to "revert" an html_safe declaration, pretty unusual.

Prepending your expression with raw is actually equivalent to calling to_s chained with html_safe on it, but is declared on a helper, just like h, so it can only be used on controllers and views.

"SafeBuffers and Rails 3.0" is a nice explanation on how the SafeBuffers (the class that does the html_safe magic) work.

Tuesday, June 1, 2021
 
superfell
answered 7 Months ago
73

EDIT: You should use the DOMParser API as Wladimir suggests, I edited my previous answer since the function posted introduced a security vulnerability.

The following snippet is the old answer's code with a small modification: using a textarea instead of a div reduces the XSS vulnerability, but it is still problematic in IE9 and Firefox.

function htmlDecode(input){
  var e = document.createElement('textarea');
  e.innerHTML = input;
  // handle case of empty input
  return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}

htmlDecode("&lt;img src='myimage.jpg'&gt;"); 
// returns "<img src='myimage.jpg'>"

Basically I create a DOM element programmatically, assign the encoded HTML to its innerHTML and retrieve the nodeValue from the text node created on the innerHTML insertion. Since it just creates an element but never adds it, no site HTML is modified.

It will work cross-browser (including older browsers) and accept all the HTML Character Entities.

EDIT: The old version of this code did not work on IE with blank inputs, as evidenced here on jsFiddle (view in IE). The version above works with all inputs.

UPDATE: appears this doesn't work with large string, and it also introduces a security vulnerability, see comments.

Tuesday, June 1, 2021
 
Wookai
answered 7 Months ago
65

I have used the Apache Commons StringEscapeUtils.unescapeHtml4() for this:

Unescapes a string containing entity escapes to a string containing the actual Unicode characters corresponding to the escapes. Supports HTML 4.0 entities.

Tuesday, June 1, 2021
 
kmunky
answered 7 Months ago
40

Try this :

<% if user_signed_in? %>
  <%= render 'form' %>
<% end %>

If you do <%= ... %>, it will try to output the thing you put between the tags. But, if you do <% ... %>, then no output is processed, just the code is evaluated. If this is not working, then there is probably something wrong with your user_signed_in? helper method.

Friday, August 13, 2021
 
Aamir
answered 4 Months ago
12

Your using <%= %> where you need <% %>. Since each returns the object it iterated over, once you are done iterating over updates, updates is returned and output to the HTML

<% @cause.updates.each do |update| # remove the = at the beginning of this line %>
  <div class="streamComment group">

  <img class="userPhoto" src="<%= update.user.avatar.url %>">

  <p class="userComment"><%= update.update_text %></p>
  </div>
<% end %>
Monday, August 30, 2021
 
Bruno
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share