Rails: Different flavors of concatting HTML safe strings in helpers

This card describes different flavors for concatting HTML safe strings in a helper method in Rails. You might want to use the tag Show archive.org snapshot helper instead of the content_tag Show archive.org snapshot helper (the tag helper knows all self closing tags).

Example

We want to generate HTML like this:

<h1>Navigation</h1>
<ul>
  <li>Left</li>
  <li>Right</li>
</ul>

Below you can find multiple helper variants that generate this markup.

Variant: HTML safe

def navigation_with_html_safe
  outer_html = ''.html_safe

  outer_html << content_tag(:h1, 'Navigation')
  outer_html << content_tag(:menu) do
    inner_html = ''.html_safe

    inner_html << content_tag(:li, 'Left')
    inner_html << content_tag(:li, 'Right')
    inner_html
  end

  outer_html
end

To prevent possible XSS vulnerabilites make sure to have a look at how to use html_safe correctly.

Variant: Plus

def navigation_with_plus
  h1 = content_tag(:h1, 'Navigation')

  menu = content_tag(:menu) do
    content_tag(:li, 'Left') + content_tag(:li, 'Right')
  end

  h1 + menu
end

The plus operator can also be used in combination with the 'HTML safe' variant from above.

Variant: Concat

Important

This variant requires you to use capture to avoid unexpected output Show archive.org snapshot when using the helper

def navigation_with_concat
  capture do
    concat(content_tag(:h1, 'Navigation'))
    concat(content_tag(:menu) do
      concat(content_tag(:li, 'Left'))
      concat(content_tag(:li, 'Right'))
    end)
  end
end

Variant: Safe join

def navigation_with_safe_join
  safe_join([
    content_tag(:h1, 'Navigation'),
    content_tag(:menu) do
      safe_join([
        content_tag(:li, 'Left'),
        content_tag(:li, 'Right')
      ])
    end
  ])
end
Emanuel 10 days ago