Read more

Rails: Different flavors of concatting HTML safe strings in helpers

Emanuel
April 24, 2024Software engineer at makandra GmbH

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

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

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
April 24, 2024Software engineer at makandra GmbH
Posted by Emanuel to makandra dev (2024-04-24 08:34)