2009-08-23 11 views
3

Je suis nouveau sur les rails et j'apprécierais une aide pour optimiser mon utilisation de la base de données.Rails: comment charger 2 modèles via join?

Existe-t-il un moyen de charger deux modèles associés les uns aux autres avec une requête DB?

J'ai deux modèles Personne et image:

class Person < ActiveRecord::Base 
    has_many :images 
end 

class Image < ActiveRecord::Base 
    belongs_to :person 
end 

Je voudrais charger un groupe de personnes et leurs images associées à un seul voyage à la DB en utilisant une commande de jointure. Par exemple, dans SQL, je peux charger toutes les données dont j'ai besoin avec la requête suivante:

select * from people join images on people.id = images.person_id where people.id in (2, 3) order by timestamp; 

J'espérais que ce rails bout ferait ce que je dois:

>> people_and_images = Person.find(:all, :conditions => ["people.id in (?)", "2, 3"], :joins => :images, :order => :timestamp) 

Ce code exécute l'instruction SQL que j'attends et charge les instances de Person dont j'ai besoin. Cependant, je vois que l'accès aux images d'une personne conduit à une requête SQL supplémentaire.

>> people_and_images[0].images 


Image Load (0.004889) SELECT * FROM `images` WHERE (`images`.person_id = 2) 

Utilisation de l': option include dans l'appel à trouver() ne se charge les deux modèles, mais il va me coûter une somme supplémentaire SELECT en l'exécutant en même temps que la jointure.

Je voudrais faire dans Rails ce que je peux faire en SQL qui est de saisir toutes les données dont j'ai besoin avec une requête.

Toute aide serait grandement appréciée. Merci!

+0

Avez-vous trouvé une solution? J'apprécierais vraiment toute aide – Ben

Répondre

2

Vous voulez utiliser :include comme

Person.find(:all, :conditions => ["people.id in (?)", "2, 3"], :include => :images, :order => :timestamp) 

Vérifiez les find documentation for plus de détails

+0

Salut Rob, je peux ne pas comprendre: inclure très bien, mais comme indiqué dans la poste, je vois via l'Analyseur de requêtes que: include provoque toujours un SELECT supplémentaire à exécuter. Donc, en SQL brut, j'exécute une requête. Dans Rails, il semble que j'ai besoin de deux. – growlyface

+0

Non, l'inclusion doit le faire dans une requête. Probablement c'est un meilleur lien pour expliquer comment cela est fait. http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html Etes-vous sûr que c'est la deuxième requête qui ne vient pas d'autre chose? –

+0

Peut-être que je suis induit en erreur par mes journaux. J'utilise le plugin query analyzer (http://agilewebdevelopment.com/plugins/query_analyzer) pour voir les instructions sql qui sont exécutées sur ma base de données. Cet appel: people_and_images = Person.find (: all,: conditions => ["people.id in (?) "," 2, 3 "],: jointures =>: images,: order =>: timestamp,: include =>: images) Indique deux instructions select en cours d'exécution (voir le commentaire suivant): – growlyface

0

Vous pouvez utiliser: inclure pour le chargement désireux d'associations et en effet il ne remet exactement 2 requêtes au lieu d'un comme avec le cas de: jointures; la première requête consiste à charger le modèle principal et la seconde à charger les modèles associés. Ceci est particulièrement utile pour résoudre l'infâme problème de requête N + 1, auquel vous devrez faire face si vous n'utilisez pas: include, et: jointures ne charge pas les associations. La différence entre utiliser: joins et: include est de 1 requête more pour: include, mais la différence de ne pas utiliser: include sera beaucoup plus.

vous pouvez le vérifier ici: http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

+0

Salut Staelen, Je pense que mon post est embrouiller les gens ma question est vraiment: si je peux saisir toutes les données dont j'ai besoin d'une seule Requête de jointure SQL, pourquoi je ne peux pas faire la même chose dans Rails Je ne demande pas vraiment comment peupler les 2 modèles, mais je demande pourquoi je ne peux pas remplir les 2 modèles avec l'appel qui me donne toutes les données dont j'ai besoin? In th Dans l'exemple ci-dessus, la commande find() avec l'option: joins se traduit par une requête de jointure SQL qui récupère toutes les données nécessaires pour remplir les modèles Person et Image. Cependant, les rails finissent seulement par remplir le modèle Person, ce qui est inefficace. – growlyface

+0

Je pense que ce blog explique en quelque sorte beaucoup plus et vous donne une meilleure idée de ce qui se passe: http://akitaonrails.com/2008/5/26/rolling-with-rails-2-1-the-first- full-tutoriel-partie 2 = elle pourra être utile) – Staelen

+0

départ optimisé Désireuse section de chargement =) – Staelen

Questions connexes