hard-code
hard-code

Reputation: 180

Rails: how to return valid javascript from controller?

A have the following action in controller:

def new_messages
    @new_msgs = Message.find(:all, order: 'id desc', limit: 12)
    respond_to do |format|
        format.js
    end
end

and javascript erb file 'new_messages.js.erb' that returns to client after new_messages action:

var data = '';
<% @new_msgs.each do |m| %>
    data += '<tr><td><%= m.user.name %></td><td><%= m.text %></td><td><%= m.created_at %></td></tr>';
<% end %>

$('#messages-table').html('');
$('#messages-table').append(data);

Here I just compose rows for new messages and try to append result to my table '#messages-table'. But there is the issue: browser gets invalid javascript from server (according to Network -> request -> Response tab in Chrome Developer Tools):

var data = '';
    data += '<tr><td>dime</td><td>cowboys from hell
</td><td>2014-01-24 15:11:36 UTC</td></tr>';

$('#messages-table').html('');
$('#messages-table').append(data);

Line break in the line #2 causes SyntaxError: Unexpected token ILLEGAL. Is it possible to return javascript as it is in my new_messages.js.erb file? How to avoid such dangerous behavior?

Upvotes: 0

Views: 70

Answers (2)

emrahbasman
emrahbasman

Reputation: 2013

Main advantage of js.erb files is using html templates in it. You should do something like below.

_your_partial.html.erb

<% @new_messages.each do |m| %>
<tr><td><%= m.user.name %></td><td><%= m.text %></td><td><%= m.created_at %></td></tr>
<% end %>

js.erb

$('#messages-table').html('');
$('#messages-table').append(<%=j render "your_partial" %>);

Upvotes: 1

vee
vee

Reputation: 38645

You should be using escape_javascript or it's alias j to escape carriage returns, single and double quotes for JavaScript.

So updating your new_messages.js.erb to the following should work:

var data = '';
<% @new_msgs.each do |m| %>
    data += '<%= j "<tr><td>#{m.user.name}</td><td>#{m.text}</td><td>#{m.created_at}</td></tr>" %>';
<% end %>

$('#messages-table').html(data);

You could also use only html(data) instead of html('') then append(data).

Upvotes: 1

Related Questions