Question: Rails 4.2 rendering an Array in js.erb results in a crash

Question

Rails 4.2 rendering an Array in js.erb results in a crash

Answers 2
Added at 2016-12-23 02:12
Tags
Question

So, I'm trying to render an Array of objects in my js.erb file. My controller method that's make the array looks like below:

def process_report
  start_date = Date.parse(params[:start_date])
  finish_date = Date.parse(params[:finish_date])
  done = params[:done].to_i
  kind = params[:kind].to_i
  late = to_boolean params[:late]
  @invoices = Invoice.where(due_date: start_date..finish_date,
                            done: done,
                            kind: kind,
                            late: late)
  if params[:approved] != ""
    @invoices = @invoices.reject{ |i| i.status.description != params[:approved] }
  end
  render 'complete_report.js.erb',
         collection: @invoices, format: :js, status: :ok
end

I know it's a little bit ugly this code. I'm intend to refactoring it. So, if the view passes the params[:approved], I reject some objects from the collection. If the view didn't pass this param, the reject method isn't called and @invoices is an ActiveRecord::Relation. As you guys can see at the end of this method, I render an js.erb file. Inside this file, I have this code:

<% @invoices.each do |invoice| %>
  var tableLine = $("<%= escape_javascript (render partial: 'invoice', locals: {invoice: invoice}, formats: :html) %>");
  $("#report_invoice_table").append(tableLine);
<% end %>

The javascript code executes normally when @invoices is an ActiveRecord::Relation. The problems comes up if params[:approved] isn't empty. The reject method filter the objects that I don't want, but returns @invoices as an Array. When it's an Array, the javascript code simply don't execute. I don't even get an error.

So, concluding: why when I passes an ActiveRecord::Relation to the js.erb so it can be rendered, my javascript code works normally and did not when I passes an Array?

I searched a lot and didn't got close of finding the answer. Sorry for the bad english. Feel free to correct me.

Thanks in advance.

Answers to

Rails 4.2 rendering an Array in js.erb results in a crash

nr: #1 dodano: 2016-12-23 11:12

Try to render it as a collection:

var tableLine = $("<%= j render(partial: 'invoice', collection: @invoices, formats: :html) %>");
$("#report_invoice_table").append(tableLine);
nr: #2 dodano: 2016-12-23 14:12

I find out the problem. In js.erb file, I got the a code that calculates the sum of all invoices after trying to rendering the invoices.

<% @invoices.each do |invoice| %>
  <% puts invoice.inspect %>
  var tableLine = $("<%= escape_javascript (render partial: 'invoice', 
    locals: {invoice: invoice}, formats: :html) %>");
  $("#report_invoice_table").append(tableLine);
<% end %>

<% if @invoices.empty? %>
  $("#report_total_value").css("display", "none");
<% else %>
  $("#report_total_value").css("display", "inline-block");
  $("#report_total_value").text("Total: R$ " + <%= @invoices.sum(:value) %>);
<% end %>

As you can see, I use the .sum method. All the problem was caused because .sum is a method only available to ActiveRecord::Relation. For the Array class, it must use another method.

<% @invoices.each do |invoice| %>
  <% puts invoice.inspect %>
  var tableLine = $("<%= escape_javascript (render partial: 'invoice',
    locals: {invoice: invoice}, formats: :html) %>");
  $("#report_invoice_table").append(tableLine);
<% end %>

<% if @invoices.empty? %>
  $("#report_total_value").css("display", "none");
<% else %>
  $("#report_total_value").css("display", "inline-block");
  $("#report_total_value").text("Total: R$ "
  + <%= @invoices.map{ |i| i.value }.reduce(0, :+) %>);
<% end %>

After changed it, my code works fine.

Source Show
◀ Wstecz