¿Cómo reducir (masivamente) el número de consultas SQL en la aplicación Rails?

En mi aplicación Rails tengousers que puede tener muchosinvoices el cual a su vez puede tener muchospayments.

Ahora en eldashboard Ver Quiero resumir todo elpayments a user ha recibido, ordenado por año, trimestre o mes. lospayments también se subdividen enbruto, redyimpuesto.

usuario.rb:

class User < ActiveRecord::Base

  has_many  :invoices
  has_many  :payments

  def years
    (first_year..current_year).to_a.reverse
  end

  def year_ranges
    years.map { |y| Date.new(y,1,1)..Date.new(y,-1,-1) }
  end

  def quarter_ranges
    ...
  end

  def month_ranges
    ...
  end

  def revenue_between(range, kind)
    payments_with_invoice ||= payments.includes(:invoice => :items).all
    payments_with_invoice.select { |x| range.cover? x.date }.sum(&:"#{kind}_amount") 
  end

end

factura.rb:

class Invoice < ActiveRecord::Base

  belongs_to :user
  has_many :items
  has_many :payments

  def total
    items.sum(&:total)
  end

  def subtotal
    items.sum(&:subtotal)
  end

  def total_tax
    items.sum(&:total_tax)
  end

end

pago.rb:

class Payment < ActiveRecord::Base

  belongs_to :user
  belongs_to :invoice  

  def percent_of_invoice_total
    (100 / (invoice.total / amount.to_d)).abs.round(2)
  end

  def net_amount
    invoice.subtotal * percent_of_invoice_total / 100
  end  

  def taxable_amount
    invoice.total_tax * percent_of_invoice_total / 100
  end

  def gross_amount
    invoice.total * percent_of_invoice_total / 100
  end

end

dashboards_controller:

class DashboardsController < ApplicationController

  def index    
    if %w[year quarter month].include?(params[:by])   
      range = params[:by]
    else
      range = "year"
    end
    @ranges = @user.send("#{range}_ranges")
  end

end

index.html.erb:

<% @ranges.each do |range| %>

  <%= render :partial => 'range', :object => range %>

<% end %>

_range.html.erb:

<%= @user.revenue_between(range, :gross) %>
<%= @user.revenue_between(range, :taxable) %>
<%= @user.revenue_between(range, :net) %>

Ahora el problema es que este enfoque funciona, pero también produce una gran cantidad de consultas SQL. En un tipicodashboard vista obtengo100+ Consultas SQL Antes de añadir.includes(:invoice) Hubo aún más consultas.

Supongo que uno de los principales problemas es que cada facturasubtotal, total_tax ytotal no se almacenan en ninguna parte de la base de datos, sino que se calculan con cada solicitud.

¿Alguien puede decirme cómo acelerar las cosas aquí? No estoy muy familiarizado con SQL y el funcionamiento interno de ActiveRecord, por lo que probablemente ese sea el problema aquí.

Gracias por cualquier ayuda.

Respuestas a la pregunta(3)

Su respuesta a la pregunta