1

I'm trying have the HTML tag <br> interpreted as a line break, but instead it displays as a string literal in the view when I attempt this:

<%= property.address_line_2 + "<br>" if property.address_line_2.present? %>

I tried raw() and .html_safe but they the same effect.

<%= property.address_line_2 + raw("<br>") if property.address_line_2.present? %>

<%= property.address_line_2 + "<br>".html_safe if property.address_line_2.present? %>

Is there an elegant/idiomatic way of doing this, or is the best way to use another line? I figure this approach is just not so DRY:

<%= property.address_line_2 if property.address_line_2.present? %>
<% if property.address_line_2.present? %><br><% end %>
stevec
  • 41,291
  • 27
  • 223
  • 311

2 Answers2

2

I would use

<% if property.address_line_2.present? %>
  <%= property.address_line_2 %><br>
<% end %>

This also has the added benefit of being a bit easier to read

RobbeVP
  • 379
  • 3
  • 9
1

html_safe string has to be returned for tags to not be escaped:

<%= "<br>".html_safe %>

When html_safe string, aka ActiveSupport::SafeBuffer, is concatenated to a regular string, aka String, the result is a regular unescaped string:

>> "<br>".html_safe.class
=> ActiveSupport::SafeBuffer
>> ("address" + "<br>".html_safe).class
=> String
>> ("address" + "<br>".html_safe).html_safe?
=> false

raw is just a helper method that does the same thing, but calls to_s first: .to_s.html_safe

>> include ActionView::Helpers::OutputSafetyHelper
>> ("address" + raw("<br>")).html_safe?
=> false
>> raw("address" + "<br>").html_safe?
=> true
# NOTE: this doesn't work
>> ("address".html_safe + "<br>").html_safe?
=> true
# but the tag is escaped
>> "address".html_safe + "<br>"
=> "address&lt;br&gt;"

If you have to concatenate tags as strings, mark the whole result as html safe:

<%= (property.address_line_2 + "<br>").html_safe %>

<%= property.address_line_2.html_safe + "<br>".html_safe %>

<%= raw(property.address_line_2 + "<br>") %>

<%== property.address_line_2 + "<br>" %>

Use safe_join helper if you don't want to risk making the entire string safe, but still want to add a tag:

<%= safe_join [property.address_line_1, "<br>".html_safe] %>

Do the whole address in one go:

<% address_1 = "1st Street NE"; address_2 = " "; address_3 = nil; city = "City"; state = "Sate"; country = "Country" %>

<%=
  safe_join(
    [
      address_1,
      address_2,
      address_3,
      [city, state].join(", "),
      country
    ].reject(&:blank?),
    tag.br
  )
%>

# returns html safe string
"1st Street NE<br>City, Sate<br>Country"

# and renders
1st Street NE
City, Sate
Country

Also just use plain erb:

<% if (line = property.address_line_1.presence) %>
  <%= line %>
  <br>
<% end %>

https://api.rubyonrails.org/classes/String.html#method-i-html_safe

https://api.rubyonrails.org/classes/ActionView/Helpers/OutputSafetyHelper.html#method-i-raw

https://api.rubyonrails.org/classes/ActionView/Helpers/OutputSafetyHelper.html#method-i-safe_join

https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-tag

Alex
  • 16,409
  • 6
  • 40
  • 56