Advanced usage of content_tag helper

Ruby on Rails / Views

Generally, there are two common ways of creating HTML code in your Ruby on Rails app views: you can simply write HTML code or generate it by using helpers from ActionView module. This time we would focus on content_tag helper – it provides some options that are not widely known.

You can test it with me by running rails console and including ActionView::Helpers::TagHelper and ActionView::Context modules. The first module is included to be able to access content_tag helper and the second to be able to test nested tags.

Base usage

Our helper requires at least one argument. Element name is always required:

content_tag(:div) #=> "< div >< /div >"

As second argument you can pass element content:

content_tag(:div, "content") #=> "< div >content< /div >"

If it’s not enough, you can have nested tags:

content_tag(:div) do
  content_tag(:strong, "header")
end #=> "< div >< strong >header< /strong >< /div >"

Attributes

You can pass also extra options to your elements. class would be one of most commonly used tags so let’s test it:

content_tag(:div, "header", class: 'link') #=> "< div class="link" >header< /div >"

Sometimes you may need to pass class name dynamically and it’s important to pass nil instead of a blank string when there is no class name. Here is why:

content_tag(:div, "header", class: "") #=> < div class="" >header< /div >
content_tag(:div, "header", class: nil) #=> "< div >header< /div >"

You can also pass multiple classes at once:

content_tag(:div, "header", class: ["one", "two"]) #=> "< div class="one two" >header< /div >"

Escaping attributes

By the default attributes are escaped so if you would pass HTML code as an attribute (from the database for example when you gave your users ability to use rich text editors) you will receive escaped output:

content_tag(:div, "")

You probably didn’t expect such output. Fortunately, there is a fourth option, default set to true which determines if attributes should be escaped:

content_tag(:div, "", {}, false) #=> < div >< div >< /div >< /div >

And that’s it. This little helper may be very useful in our views so it’s always nice to know what we can do more with it