Don't escape html in ruby on rails

Ruby on-RailsRuby on-Rails-3

Ruby on-Rails Problem Overview


rails 3 seems to escape everything, including html. I have tried using raw() but it still escapes html. Is there a workaround? This is my helper that I am using (/helpers/application_helper.rb):

module ApplicationHelper
  def good_time(status = true)
    res = ""
    if status == true
      res << "Status is true, with a long message attached..."
    else
      res << "Status is false, with another long message"
    end
  end
end

I am calling the helper in my view using this code:

<%= raw(good_time(true)) %>

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

You can use .html_safe like this:

def good_time(status = true)
  if status
    "Status is true, with a long message attached...".html_safe
  else
    "Status is false, with another long message".html_safe
  end
end

<%= good_time(true) %>

Solution 2 - Ruby on-Rails

I ran into this same thing and discovered a safer solution than using html_safe, especially once you introduce strings which are dynamic.

First, the updated code:

def good_time(long_message1, long_message2, status = true)
  html = "".html_safe
  html << "Status is #{status}, "
  if status
    html << long_message1
  else
    html << long_message2
  end
  html
end

<%= good_time(true) %>

This escapes long_message content if it is unsafe, but leaves it unescaped if it is safe.

This allows "long message for success & such." to display properly, but also escapes "malicious message <script>alert('foo')</script>".

The explanation boils down to this -- 'foo'.html_safe returns an ActiveSupport::SafeBuffer which acts like a String in every way except one: When you append a String to a SafeBuffer (by calling + or <<), that other String is HTML-escaped before it is appended to the SafeBuffer. When you append another SafeBuffer to a SafeBuffer, no escaping will occur. Rails is rendering all of your views under the hood using SafeBuffers, so the updated method above ends up providing Rails with a SafeBuffer that we've controlled to perform escaping on the long_message "as-needed" rather than "always".

Now, the credit for this answer goes entirely to Henning Koch, and is explained in far more detail at [Everything you know about html_safe is wrong][1] -- my recap above attempts only to provide the essence of the explanation in the event that this link ever dies.

[1]: http://makandracards.com/makandra/2579-everything-you-know-about-html_safe-is-wrong "Everything you know about html_safe is wrong"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionalexyorkeView Question on Stackoverflow
Solution 1 - Ruby on-RailsMischaView Answer on Stackoverflow
Solution 2 - Ruby on-RailsDreadPirateShawnView Answer on Stackoverflow