October 28, 2009
Ajax responses with Rails partials
I was working on a Rails app last night and hit a problem. I thought I’d share the problem and solution.
I had a form process an Ajax call on submit and evaluate the response text. I use jQuery so keep that in mind when you read the example JavaScript code.
1 2 3 4 5 6 |
// main.js $('form[data-remote=true]').submit(function(){ $form = $(this); $.post($form.attr('action'), $form.serialize(), false, 'script'); return false; }); |
You’ll notice the “data-remote=true” part. Disregard that. It’s just something coming down the pipes in Rails 3. So the JavaScript works. My controller works and renders the appropriate view.
1 2 |
// update.js.erb $('#entries ol').append('<%= render(:partial => "entries/item", :locals => { :entry => @entry, :list => @list }) %>'); |
Thats the view rendered by the controller. You’ll see the view renders a partial within it.
1 2 3 4 5 6 7 8 |
<!-- entries/_item.html.erb --> <li class="entry<%= cycle('', ' alt') %>" id="entry-<%= entry.id %>"> <menu> <li><%= link_to "Update #{entry.name}", list_entry_path(list, entry), :class => "update" %></li> <li><%= link_to "Remove #{entry.name}", list_entry_path(list, entry), :class => "destroy" %></li> </menu> <p><%= entry.name %></p> </li> |
Well everything looks pretty good, but I kept getting the JavaScript error “unterminated string literal.” This is due to the line breaks in the entries/_item partial.
1 2 3 4 5 6 7 8 |
// will work $('#entries ol').append('<li>\n\tThis is a new line\n\tThis is a second line\n</li>'); // this will not work $('#entries ol').append('<li> This is a new line This is a second line </li>'); |
To fix this I modified my update.js.erb view slightly. I added gsub("\n","").
1 2 |
// update.js.erb modified $('#entries ol').append('<%= render(:partial => "entries/item", :locals => { :entry => @entry, :list => @list }).gsub("\n","") %>'); |
After pulling out the line breaks the JavaScript error disappeared. Hope this helps!

August 20, 2010
Try the helper #escape_javascript or maybe #to_json on #render’s return value.