2016-05-15 8 views
1

Ich habe derzeit eine harte Zeit, eine Lösung für ein Problem in einem Ruby on Rails-Projekt zu finden.Abfrage Ergebnis mit Baum der referenzierten Objekte - Ruby on Rails

Ich habe folgende Modellstruktur:

class Room < ActiveRecord::Base 
    has_many :photos 
end 

class Photo < ActiveRecord::Base 
    belongs_to :room 
    has_many :points 
end 

class Point < ActiveRecord::Base 
    belongs_to :photo 
end 

Ich möchte die Datenbank abzufragen, so dass ich etwas, das als JSON gemacht würde diese Struktur haben:

{ 
     "rooms" : 
      [ 
       //room 1 
       { 
        "id": 1, 
        "param1": "dummy", 
        "photos": 
         [ 
          { 
           "id": 3, 
           "title": "test photo", 
           "points": 
            [ 
             {"id": 1, "text": "test point"}, 
             {"id": 2, "text": "test point"} 
            ] 
          } 
         ] 

       }, 
       //room 2 
       { 
        "id": 2, 
        // ... 
       } 
      ] 
    } 
 

Grundsätzlich möchte ich um eine Abfrage zu erstellen, die alle Informationen in allen Modellen zurückgibt, die nach den Beziehungen der Modelle strukturiert sind.

Ich suchte nach ein paar Stunden und kann keine einfache Lösung für diese finden ... (nicht einmal eine komplizierte). Ich weiß nicht, ob ich nicht die richtigen Suchbegriffe für mein Problem, aber ich konnte wirklich nichts finden, was funktioniert ...

Für eine Teillösung (um nur Zimmer und Fotos zu bekommen), ich dies versucht:

Room.all.includes(:photos) 

Von dem, was ich fand, dachte ich, es die Lösung sein könnte, aber es gibt nur die Informationen über die Zimmer, nicht die Fotos, so wahrscheinlich ist dies eine völlig andere Herangehensweise an das, was ich brauche .

+0

Ich aktualisierte meine Antwort mit Ihre vorgeschlagene Bearbeitung, wenn Sie sie akzeptieren möchten –

Antwort

3

@ dankohns Antwort ist richtig für das eifrige Laden verschachtelter Assoziationen, aber ich glaube, dass du ein bisschen mehr brauchst, um mit to_json zu arbeiten. Das Problem, das ich glaube, ist to_json schaut nur auf den ursprünglichen Satz von Objekten und weiß nicht über die eifrig geladenen Assoziationen. Aber glücklicherweise ist to_json ein Methodenaufruf, der die Includes als einen festgelegten Hash der Optionen annehmen kann. (Ein Problem bei im ursprünglichen Code Wäre die @ norim_13 richtig geholfen. Danke !!)

Room.all.to_json({:include => { :photos => {:include => { :points => {}} }}}) 

https://www.tigraine.at/2011/11/17/rails-to_json-nested-includes-and-methods Rails: Eager loading as_json includes

Hier ist die Dokumentation für as_json http://apidock.com/rails/ActiveModel/Serializers/JSON/as_json

und hier in der Quelle für to_json können Sie sehen, es übergibt seinen Hash der Optionen an as_json http://apidock.com/rails/Hash/to_json

+0

Dieser erste Link war sehr hilfreich. Der benötigte Code ist nicht das, was Sie vorgeschlagen haben, aber es ist etwas Ähnliches. Ich schlage dem Beitrag eine Bearbeitung mit dem Arbeitscode vor. –

+0

Ehrfürchtig, ich bin mir sehr nahe gekommen. –

+1

Jemand aktualisiert es für mich, ich bearbeitet und gab @ norim_13 Kredit. Vielen Dank –

1

Überarbeitete:

Was bekommen Sie mit:

Room.all.includes(photos: :points).to_json 

Für mehr Informationen, Rails - Nested includes on Active Records?

+0

"Assoziation mit dem Namen 'Punkte' wurde nicht auf Raum gefunden; vielleicht hast du es falsch geschrieben? " Es verbindet die Tabelle" points "mit" rooms "und wirft einen Fehler auf weil die nicht direkt verbunden sind ... –

+0

habe ich auch nur ausprobiert: Room.all.includes (: fotos).to_json, aber obwohl es keine Fehler verursacht, gibt es nur Informationen über die Räume zurück, nicht die Fotos darin. –

+0

Ich habe Ihre überarbeitete Antwort gesehen und den Link überprüft, und es scheint, dass Ihr Vorschlag ist, was ich brauche, aber es funktioniert nicht ... Das Ergebnis ist, wieder nur die Zimmer Info ... (das gleiche wie Zimmer .all) –

0

sehen Wenn Sie zum Zerreißen bekommen, könnte es einfacher, nur eine Serie zu schreiben sein von .each Schleifen und dann nur die JSON-String manuell um sie herum aufzubauen ..

Room.all.each do |room| 
    room.photos.each do |photo| 
    photo.points.each do |point| 
     // inner loop 
    end 
    end 
end 
+0

Sei vorsichtig damit. Dies würde einige verrückte N + 1 Abfragen erzeugen, wenn Sie nicht eifrig laden. –

+0

Danke für den Vorschlag. Auch wenn mir jemand bereits den "richtigen" Ansatz gegeben hat, werde ich wahrscheinlich so etwas verwenden, um einigen Objekten benutzerdefinierte Schlüssel zu geben. –