Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to escape value returned by a yield

I recently had a problem to escape value returned by a yield in a template.

In my layout, i yield the meta description so that i can define it from my template

<meta name="description" content="<%= yield :html_description %>" />

And here is my template, that unfortunatly, does not escape the value as expected:

<% content_for :html_description, 'hello "you" guy' %>
<meta name="description" content="hello "you" guy" />

I tried to escape it with the h() escaper, but it doesnt work:

<meta name="description" content="<%= h(yield :html_description) %>" />
<meta name="description" content="hello "you" guy" />

I also tried with escape_once(), but it does too much:

<meta name="description" content="<%= escape_once(yield :html_description) %>" />
<meta name="description" content="hello &amp;quot;you&amp;quot; guy" />

However, by concatenating the returned value with a string, it fixes the problem:

<meta name="description" content="<%= '' + (yield :html_description) %>" />
<meta name="description" content="hello &quot;you&quot; guy" />

Does anyone understand this behaviour?

Do you have a better solution than this concatenation that fix it by coincidence?

I'm using Rails 2.3.8 - Thanks!

like image 785
Guillaume Avatar asked Nov 05 '10 08:11

Guillaume


2 Answers

For self-closed tags such as meta, img, or br, you can use the "tag" method.

<%= tag(:meta, :name => 'description', :content => yield(:html_description)) %>

This gives you

<meta content="&quot;I am surrounded by quotes&quot;" name="description" />
like image 185
blim8183 Avatar answered Nov 20 '22 16:11

blim8183


the 'h' function only escapes invalid html. The problem with your code is that quotes are not invalid html. Otherwise you couldn't have quotes anywhere in your webpage. "h" is there to do things like turn "<script>" into "&lt;script&gt;" instead.

so... *waves hand* this is not the method you are looking for.

What will probably solve it for you is actually using rails methods to create the meta-tag itself - and then rails will nicely escape it for you.

eg, if you tried the following:

<%= content_tag(:meta, nil, :name => 'description', :content => yield(:html_description)) %>

you'd end up with:

<meta content="hello &quot;you&quot; guy" name="description"></meta>

Update:

Oh, and the reason why string-concatenation does the trick is that the newer versions of Rails will html-safe what it considers to be a dirty string... however, it's a hack you don't need to us if you use a railsy way of generating the meta tag.

like image 30
Taryn East Avatar answered Nov 20 '22 16:11

Taryn East