From 4f0871dab007086cbf1cab39356b05112e3e06ad Mon Sep 17 00:00:00 2001 From: Nicolas Bouilleaud Date: Fri, 20 Sep 2019 08:51:54 +0200 Subject: [PATCH] Use a single query in dossiers_id_with_notifications (instead of four) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is used in /procedures#show and /procedures#index, to display badges on the “suivis” and “traités” tabs of each procedure. Rails cache helps when it’s the exact same query, but it’s not the case for different tabs. I’m not certain it’ll be a visible performance improvement but it shouldn’t hurt. --- app/models/instructeur.rb | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb index 6334d9fa7..32080dc76 100644 --- a/app/models/instructeur.rb +++ b/app/models/instructeur.rb @@ -145,30 +145,26 @@ class Instructeur < ApplicationRecord def dossiers_id_with_notifications(dossiers) dossiers = dossiers.followed_by(self) - updated_demandes = dossiers - .joins(:champs) + # Relations passed to #or must be “structurally compatible”, i.e. query the same tables. + joined_dossiers = dossiers + .left_outer_joins(:champs, :champs_private, :avis, :commentaires) + + updated_demandes = joined_dossiers .where('champs.updated_at > follows.demande_seen_at') - updated_annotations = dossiers - .joins(:champs_private) - .where('champs.updated_at > follows.annotations_privees_seen_at') + # We join `:champs` twice, the second time with `has_many :champs_privates`. ActiveRecord generates the SQL: 'LEFT OUTER JOIN "champs" "champs_privates_dossiers" ON …'. We can then use this `champs_privates_dossiers` alias to disambiguate the table in this WHERE clause. + updated_annotations = joined_dossiers + .where('champs_privates_dossiers.updated_at > follows.annotations_privees_seen_at') - updated_avis = dossiers - .joins(:avis) + updated_avis = joined_dossiers .where('avis.updated_at > follows.avis_seen_at') - updated_messagerie = dossiers - .joins(:commentaires) + updated_messagerie = joined_dossiers .where('commentaires.updated_at > follows.messagerie_seen_at') .where.not(commentaires: { email: OLD_CONTACT_EMAIL }) .where.not(commentaires: { email: CONTACT_EMAIL }) - [ - updated_demandes, - updated_annotations, - updated_avis, - updated_messagerie - ].flat_map { |query| query.distinct.ids }.uniq + updated_demandes.or(updated_annotations).or(updated_avis).or(updated_messagerie).ids end def mark_tab_as_seen(dossier, tab)