Like you know from "How to tell ActiveRecord how to preload associations (either JOINs or separate queries)", you can tell ActiveRecord explicitly if it should use a LEFT OUTER JOIN
or a separate query to preload associations.
Here is some special case, where a simple includes
is not possible. For the diagram below we want to sort the rides
by the translated name of the departure_place
and the arrival_place
:
Here is the list of features we want to achieve:
- Paginated (using will_paginate Show archive.org snapshot )
- Ordered by translated name of
departure_place
andarrival_place
- No N+1 queries
This is normally straightforward, but as we are referencing the table we want to order on twice some adjustments need to be made.
Ride
.joins('inner join places as departure_places on ride.departure_place_id = departure_places.id')
.joins('inner join places as arrival_places on ride.arrival_place_id = arrival_places.id')
.joins('inner join place_translations as departure_place_translations on departure_places.id = departure_place_translations.place_id AND departure_place_translations.locale = "en"')
.joins('inner join place_translations as arrival_place_translations on arrival_places.id = arrival_place_translations.place_id AND arrival_place_translations.locale = "en"')
.order('departure_place_translations.name, arrival_place_translations.name')
.where(ride_id: 1)
.paginate(page: 1, per_page: 20)
.preload(
departure_place: :translations,
arrival_place: :translations
)
.to_a
What we do here:
- First make some custom SQL with
INNER JOIN
s where ourorder
constraint can be fulfilled (Power of plain SQL: Usingeager_load
here is not possible or very painful) - Then preload the result set (Power of ActiveRecord: If you don't use ActiveRecord preload you need to manually take care of pagination and ordering after fetching the records by ids)
Posted by Emanuel to makandra dev (2016-12-12 09:42)