2017-03-01 2 views
0

Wenn ich versuche, verknüpfte Daten in Index-Aktion zu zeigen - ich kann nicht vermeiden, N + 1 Problem mit Standart umfasst. Beispiel:Rails - Mehr über "N + 1"

Model 1 - Pet (let it will be animal: title:string. Pet can has many PetAttributeElems, they show attributes this Pet have and what values they have) 
Model 2 - PetAttribute (this model contains only titles of attributes, like weight, age and 1000+ more attributes. PetAttribute has many PetAttributeElems - one attribute, such as weight, can be described for many Pets) 
Model 3 - PetAttributeElem (this model belongs to pet and to petAttribute, also it has value field, that show value of attribute for pet. 

Als ich show Aktion machen - ich in HAML:

[email protected]_attribute_elems.includes(:pet_attribute).each do |elem| 
     ="#{elem.pet_attribtute.title}: #{elem.value}" 

Aber wenn ich index Aktion machen möchte ich nutzen, um:

[email protected] do |pet| 
    -pet.pet_attribute_elems.includes(:pet_attribute).each do |elem| 
    ="#{elem.pet_attribtute.title}: #{elem.value}" 

Das includes Methode nennen viele SQL-Abfragen, für jede pet

Jetzt löse ich es manuell durch zusätzliche Objekt wie folgt erstellen:

@pet_elems = {} 
PetAtributeElems.includes(:pet_attribute) 
    .where(pet_id:@pets.map(&:id)).each do |elem| 
    pet_id = elem.pet_id 
    if @pet_elems.include?(pet_id) 
    @pet_elems[pet_id] << elem 
    else 
    @pet_elems[pet_id] = [elem] 
    end 
end 

als ich verwenden kann:

[email protected] do |pet| 
    -if @pet_elems.include?(pet.id) 
    [email protected]_elems[pet.id].each do |elem| 
     ="#{elem.pet_attribtute.title}: #{elem.value}" 

Wie konnte ich diese Aufgabe leichter lösen?

+0

[Sie vielleicht‘ die falsche Aufgabe lösen (semi-related reading) ...] (https://stackoverflow.com/questions/26247288/reducing-n1-queres-using-the-bullet-and-r Spec-Gems/26251892 # 26251892) –

+0

Ich hoffe, Sie haben Recht) aber jetzt muss ich im Index Aktion verknüpfte Daten ohne N + 1 Abfragen zeigen – user2572790

Antwort

1

Sie gehen einen Nicht-Schienen-Konventionspfad.

Verschieben Code aus den Ansichten, so dass es einfach ist

= render @pet_attribute_elems 

Machen Sie eine Teilanzeige

# _pet_attribute_elems.html.haml 
="#{pet_attribute_elem.pet_attribtute.title}: #{pet_attribute_elem.value}" 

In der Steuerung zu umgehen, führen Sie die Abfragen

def show 

    @pet = Pet.find(...) 
    @pet_attribute_elems = @pet.pet_attribute_elems.includes(:pet_attribute) 

end 

def index 

    @pet_attribute_elems = PetAttributeElem.includes(:pet_attribute) 

end 
+0

vielleicht hast du Recht, aber das ist nicht lösen Problem vieler Fragen – user2572790

+0

Es werden nur ein oder zwei Abfragen sein. Das ist nicht viel – Swards