Preload can't prevent N queries when joining has-many

I’ve noticed that preloading has-one and belongs-to associations completely breaks when you join a has-many association and select certain columns that exist in both tables – maybe just id.

class Customer < ActiveRecord::Base
end
class Order < ActiveRecord::Base
  belongs_to :customer
  has_many :order_line_items
end
class OrderLineItem < ActiveRecord::Base
end


Order.left_outer_joins(:order_line_items).
  select(OrderLineItem.arel_table[Arel.star], Order.arel_table[Arel.star]).
  preload(:customer)

This seems to generate one query for the orders and line items, one preload query for the customer, then additional queries to load the customer for each additional order line item after each order’s first. Say there are M orders and N line items, the additional queries total N - M (assuming each order has at least one line item).

Hi Will! Let me see if I understand…

Do you want to do something like this?..

orders = fetch_orders
orders.each do |order|
  puts order.customer
 
  order.order_line_items.each do |item|
    puts item
  end
end

If that is your case I think that what you want to do is to also preload the line items, like this…

Order.preload(:customer, :order_line_items)

I think that you were trying to preload the line items, using left_outer_joins, but as far as I know this method is just to build the query, and will not preload the records.