Optimize your RoR search
I am creating a RoR (rails 4) project with this search and showing in a table with bootstrap 3 style.
- My following code works, but is too slow. I hope this can be optimized.
- Is there a way to show loading in the middle of the page?
I am very new to RoR and my English is not very good. I'm sorry about that. Please help me! and thanks for everything!
<div class="panel panel-primary">
<div class="panel-body">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Grado</th>
<% meses = ((@cargo_total_grado.fecha_inicio)..@cargo_total_grado.fecha_final).map {|d| [d.strftime('%b'), d.year]}.uniq %>
<% meses.each do |m| %>
<th> <%= m.first + " " + m.second.to_s %> </th>
<% end %>
<th>Total</th>
</tr>
</thead>
<tbody>
<% @cursos.each do |curso| %>
<% alumnos = Alumno.select("id").where(:id => curso.alumno_ids) %>
<tr>
<td><small><%= curso.id_curso %></small></td>
<% total = 0 %>
<% meses.each do |m| %>
<% inicio = (m.second.to_s + m.first.to_s + "-01").to_date %>
<% final = inicio.next_month %>
<% mes = alumnos.map { |e| e.planes.map {|r| r.cargos.where("fecha_cargo >= ? AND fecha_cargo < ?", inicio, final).sum(:monto)}.sum }.sum %>
<% total += mes %>
<td><small> <%= number_to_currency(mes) %> </small></td>
<% end %>
<th><small><%= number_to_currency(total) %></small></th>
</tr>
<% end %>
<tr>
<th></th>
<% totales = 0 %>
<% meses.each do |m| %>
<% inicio = (m.second.to_s + m.first.to_s + "-01").to_date %>
<% final = inicio.next_month %>
<% mes_total = @cursos.map { |c| c.alumnos.map { |e| e.planes.map {|r| r.cargos.where("fecha_cargo >= ? AND fecha_cargo < ?", inicio, final).sum(:monto)}.sum }.sum }.sum %>
<% totales += mes_total %>
<th><small> <%= number_to_currency(mes_total) %> </small></th>
<% end %>
<th><small><%= number_to_currency(totales) %></small></th>
</tr>
</tbody>
</table>
</br>
</div>
source to share
So, your problem is that you have too many SQL calls. Rails has to query the database for each one, which leads to a slowdown.
You should look into Eager Loading to fix this issue, commonly referred to as the N + 1 request problem .
An active entry allows you to specify in advance all associations to be loaded. This is possible by specifying a method to include the call to Model.find. With Active Record enabled, ensures that all specified associations are loaded using as few queries as possible.
For example, you seem to be loading multiple cursors into your @cursos
object and letting multiple objects load from that Alumno
and then those Cargo
objects loads . This will result in multiple calls to the database. Instead, in your model, you can do something like:
@cursos = Curso.includes(alumnos: [:cargos]).all
In the second part of your answer, is it possible to show the loading animation:
Yes, you can, BUT you will need to use AJAX calls to load information from other routes you create that return the information you need. It's not overly complicated, but it adds a bit of complexity to the application. Take a look at this if you're interested .
PS Parece que hablas español? Si hay algo que no entiendes puedo explicártelo por chat, solo me avisas cuando tengas tiempo.
source to share