Why escape_javascript before rendering a partial?

It’s easier to understand if you split the code in two parts.

The first part $("#reviews").append("<%= ... %>"); is javascript with erb. This means that the <%= ... %> will be replaced by whatever the ruby code inside of it returns. The result of that replacement must be valid javascript, otherwise it will throw an error when the client tries to process it. So that’s the first thing: you need valid javascript.

Another thing to take into account is that whatever ruby generates must be contained inside a javascript string with double quotes – notice the double quotes around the <%= ... %>. This means that the generated javascript will look like this:

$("#reviews").append("...");

Now let’s examine the ruby part inside the <%= ... %>. What does render(:partial => @review) do? It is rendering a partial – which means that it could be rendering any kind of code – html, css … or even more javascript!

So, what happens if our partial contains some simple html, like this one?

<a href="https://stackoverflow.com/mycontroller/myaction">Action!</a> 

Remember that your javascript was taking a double-quoted string as a parameter? If we simply replace the <%= ... %> with the code of that partial, then we have a problem – immediately after the href= there is a double quote! The javascript will not be valid:

// Without escaping, you get a broken javascript string at href
$("#reviews").append("<a href="https://stackoverflow.com/mycontroller/myaction">Action!</a>");

In order for this not to happen, you want to escape these special characters so your string is not cut – you need something that generates this instead:

<a href=\"/mycontroller/myaction\">Action!</a>

This what escape_javascript does. It makes sure that the string returned will not “break” javascript. If you use it, you will get the desired output:

$("#reviews").append("<a href=\"/mycontroller/myaction\">Action!</a>")

Regards!

Leave a Comment