Search code examples
ruby-on-railsstringif-statementtagshtml-safe

Rails tag(:br) not considered as html_safe


Answer at the end.

I currently refactoring my app, and I'm wondering how to short my "if" since I use them a lot in it :

What I want, is a line break <br /> only if the value isn't blank, so, for now I'm writing it this way :

<% if @card.address.street.present? %>
 <%= @card.address.street.titleize %>
 <%= tag(:br) %> ## or plain html <br />
<% end %>

It works well, but I'm sure there is a less wordy way.

I tried :

<%= @card.address.street.titleize + tag(:br) if @card.address.street.present? %>

==> Washington Road '' ## br tag ain't html_safed.

if I do :

<%= raw @card.address.street.titleize + tag(:br) if @card.address.street.present? %>

Which is equal to :

<%== @card.address.street.titleize + tag(:br) if @card.address.street.present? %>

I works well, but expose my code to XSS attack.

So, I tried :

<%= @card.address.street.titleize + raw(tag(:br)) if @card.address.street.present? %>

<%= @card.address.street.titleize + tag(:br).html_safe if @card.address.street.present? %>

<%= @card.address.street.titleize + "<br />".html_safe if @card.address.street.present? %>

==> Washington Road '' ## br tag still ain't html_safed.

Sanitize give good result on this, used like that :

<%= sanitize(@card.address.street.titleize + tag(:br)) if @card.address.street.present? %>

But is this the best way to go regarding performance?

I ended up using an helper:

Inside helpers/application_helper

def line_break value
 sanitize(value) + tag(:br)
end

Helper is loaded inside controller

class UsersController < ApplicationController
helper ApplicationHelper

I added this helper inside application one. If you want something less general on your app, a module would be prefered.

Sanitize used with empty parameters will check for html inside your string, and delete it. If you want something less heavy, you can use h() that will escape all html instead of removing it.

In the view

<%= line_break(@card.address.street.titleize) if @card.address.street.present? %>

I know it's purely a "writing speed issue" but any help would be appreciated.

Kind Regards


Solution

  • This is not because your br tag is safe or unsafe.

    The street string is unsafe and when you add a safe string to an unsafe string then the result is still unsafe.

    You could instead write this as

    <%= h(@card.address.street.titleize) + tag(:br) %>
    

    The h does the escaping and marks the result as safe (since it has just been escaped).