2017-07-26 4 views
0

Ich habe eine App, in der Benutzer einen Beitrag mit einem Lesezeichen versehen können. Um Lesezeichen zu erstellen, habe ich ein polymorphes Modell namens Bookmark erstellt.Liste der Datensätze mit Lesezeichenstatus abrufen

Jetzt muss ich die Beiträge eine Liste aller anzuzeigen (die 50 pro Seite sagen lassen, paginierte) mit einem Titel und einem Lesezeichen-Status für aktuell angemeldeten Benutzers.

Ich habe zwei Szenarien in meinem Kopf, wie ich dies erreichen kann. Und ich mag keine von ihnen.

  1. überprüfen Lesezeichen Status für jede Stelle, wenn eine Liste zu machen - dies erzeugt N + 1 Abfrage und ist im Grunde eine schreckliche Idee im Allgemeinen
  2. Hier finden Sie eine Liste der Post IDs einer aktuellen Seite, holen alle Lesezeichen für Aktueller Benutzer bookmarkable_id IN post_ids_of_current_page, überprüfen Sie, welcher Post in der Liste mit Lesezeichen vorhanden ist und zeigen Sie den Status als Lesezeichen an.

Das zweite ist ziemlich vernünftig, aber ich möchte wirklich alles in einer SQL-Abfrage fusionieren (wenn möglich, ich bin nicht sicher, ob das joins Verwendung erreicht werden kann). Es ist durch die Tatsache verursacht, dass ich es nicht in regelmäßigen Schienenansichten verwende, sondern in der API API Endpunkt + SPA-Anwendung von graphql und es ist nicht so trivial, die Auflistungs-IDs abzurufen und sie zu vergleichen. Es führt nur zu einer größeren Anzahl von Anfragen an die API, die ich gerne vermeiden würde.

Antwort

0

Es stellte sich heraus, ich kann includes Methode für diese verwenden (die zwei Abfragen erzeugen wird, aber es ist immer noch besser als N + 1). Wenn jemand eine One-Query-Version mit joins teilen kann, werde ich mehr als glücklich sein, seine Antwort zu akzeptieren, aber bis jetzt posten ich meine Lösung, die für meine Bedürfnisse genug ist.

class User 
    has_many :bookmarks, as: :bookmarker 
end 

class Post 
    has_many :bookmarks_as_bookmarkable, as: :bookmarkable, class_name: :Bookmark 

    def bookmarked_by?(bookmarker) 
    self.bookmarks_as_bookmarkable.to_a.select do |b| 
     b.bookmarker_type == bookmarker.class.name && 
     b.bookmarker_id == bookmarker.id 
    end.any? 
    end 
end 

Und die Ergebnisse:

Post.includes(:bookmarks_as_bookmarkable).map { |p| u.bookmarked_by?(current_user) }` 
# SELECT "posts".* FROM "posts" 
# SELECT "bookmarks".* FROM "bookmarks" WHERE "bookmarks"."bookmarkable_type" = ? AND "bookmarks"."bookmarkable_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30) 
# 
# => [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true] 
Verwandte Themen