includes, strict_loading & Friends

.includes β€” one method, two strategies, Rails picks

.includes(:walker, :dog) doesn't commit to a single SQL shape. Rails looks at the rest of your query and picks one of two strategies for you:

  • Preload (separate queries): SELECT FROM bookings ..., then SELECT FROM walkers WHERE id IN (...), then SELECT * FROM dogs WHERE id IN (...). Three total queries, each simple, results stitched together in Ruby. This is what index gets, because nothing in the query filters or orders by a column on walkers or dogs.
  • Eager load (one JOIN): a single LEFT OUTER JOIN query. Rails switches to this automatically the moment your .where or .order references a column on the included association β€” because a preload's separate queries can't apply a condition against a table they haven't joined yet.

You can force either by name β€” .preload(:walker, :dog) always does separate queries, .eager_load(:walker, :dog) always does one JOIN β€” but plain .includes is the right default almost everywhere: let Rails pick.