14

Hintergrund

Ich habe eine Rails-Anwendung mit tief verschachtelten Assoziationen.Eager Last Assoziationen mit Active Model Serialisierer

      .-< WorkPeriod 
Timecard -< Week -< Day -<--< Subtotal 
          `-< Adjustment 

-< (has many) 

Ich verwende Active Model Serializer die API zu bauen.

Auf der Client-Seite möchte ich eine Zeitkarte und alle ihre Assoziationen in einem Schuss laden.

Derzeit sehen meine Serializer wie diese,

class TimecardSerializer < ActiveModel::Serializer 
    embed :ids, include: true 
    has_many :weeks 
end 
class WeekSerializer < ActiveModel::Serializer 
    embed :ids, include: true 
    has_many :days 
end 
# ... etc ... 

Problem

Das alles funktioniert finden, außer nichts geladen eifrig bekommt. Daher werden für jede Anfrage viele Anrufe an die Datenbank getätigt. Für jede Woche wird eine separate Anfrage für die Tage in dieser Woche gestellt. Und für jeden Tag gibt es eine separate Anfrage für seine Arbeitsperioden, Zwischensummen und Anpassungen.

Antwort

9

Eine Lösung besteht darin, auf dem TimecardSerializer eine eigene weeks-Methode zu definieren. Von dort können Sie .includes() alle Assoziationen, die Sie gerne laden möchten.

Alle Abfragen werden immer noch im Protokoll angezeigt, aber die meisten werden eine zwischengespeicherte Abfrage statt einer echten sein.

+1

Dies ist für das Laden einer einzelnen Ressource geeignet, funktioniert aber nicht, wenn dieser Serializer verwendet wird, um eine Liste von 'Timecards' zurückzugeben. Insbesondere werden die "Wochen" nicht sehr geladen sein, obwohl die "Wochen" -Beziehungen sein werden. – hjdivad

8

Ich hatte ein ähnliches Problem. Ich habe es in meinem Controller behoben. Ich mag die Idee, es in den Serializer zu setzen, aber wenn es im Controller ist, fängt es auch das n + 1 Wochen Problem ab, das vom ArraySerializer erzeugt wird.

Timecard.find(params[:id]).includes(weeks: [{ days: [:sub_totals, :work_periods, :adjustments] }]) 

und

Timecard.includes(weeks: [{ days: [:sub_totals, :work_periods, :adjustments] }]) 

sollte nun eifrig Last und begrenzt die Abfrage nur sechs db Treffer.