2010-11-16 8 views
10

D'accord, je suis complètement perplexe sur celui-ci. J'essaye de construire un menu de pages Web publiées organisées par catégorie.Rails 3 - Envie de chargement avec des conditions

Category.rb:

belongs_to :parent, :class_name => "Category", :foreign_key => "parent_id" 
has_many :children, :class_name => "Category", :foreign_key => "parent_id" 
has_many :pages, :documents, :galleries 

Page.rb

belongs_to :category 

Le modèle Page a également: is_published, donc je suis en train de filtrer aussi. Je suis réticent à poster mes faibles tentatives de requête, mais ne vois pas d'autre solution que de demander la charité beaucoup plus intelligente:

(auto est @current_website)

self.categories.includes(:children, :pages).where('pages.is_published = 1') 

Cela renvoie la plupart du temps ce que j'ai besoin, mais pas des parents Catégories sans pages publiées. Par exemple, il fonctionne très bien si j'ai:

Parent Category 
- Published Page 
- Child Category 
-- Published Page 

Lorsqu'il échoue est quand je n'ai pas les pages publiées dans le parent, comme celui-ci:

Parent Category 
- Child Category 
-- Published Page 
- Child Category 
-- Published Page 

Merci à l'avance pour toute aide à ce sujet. J'essaie d'en apprendre le plus possible sur les requêtes, mais je suis contre le mur à ce sujet.

MISE À JOUR: La suggestion de mise en œuvre KandadaBoggu a donné de bien meilleurs résultats, cela a été ajouté à Category.rb

has_many :published_pages, :class_name => "Page", 
          :conditions => {:is_published => true} 

Cependant, lorsque vous utilisez les éléments suivants:

self.categories.where(:parent_id => nil).includes({:children => :published_pages}, 
                :published_pages) 

j'obtenir les résultats dont j'ai besoin, mais je reçois également des catégories parent vides (pas de pages publiées, pas de catégories enfants avec des pages publiées.) Un exemple:

- Parent Category 
-- Published Page 
- Parent Category 
-- NOTHING 
- Parent Category 
-- Published Page 
- Parent Category 
-- NOTHING 

Mon solution temporaire était joint la requête avec:

reject{|category| category.pages.empty? && category.children.empty?} 

Merci encore pour votre aide.

Répondre

14

Ajouter une nouvelle association appelée published_pages (en dehors de vos associations actuelles)

class Category 

    has_many :children,  :class_name => "Category", 
       :foreign_key => "parent_id" 
    has_many :published_pages, :class_name => "Page", 
       :conditions => { :is_published => true } 

end 

Maintenant vous pouvez obtenir toutes les catégories comme suit:

self.categories.includes(:children, :published_pages) 

Si vous êtes intéressé à apprendre pourquoi votre approche n'a pas fonctionné, lisez les rails documentation (faites défiler 10-15 lignes après la section Eager loading of associations).J'ai inclus l'extrait correspondant ci-dessous:

Par exemple

Post.includes([:author, :comments]).where(['comments.approved = ?', true]).all 

Cela se traduira par une seule requête SQL avec des jointures le long des lignes de:

LEFT OUTER JOIN comments ON comments.post_id = posts.id and 
LEFT OUTER JOIN authors ON authors.id = posts.author_id. 

Notez que l'utilisation des conditions comme Cela peut avoir des conséquences inattendues. Dans l'exemple ci-dessus, les messages avec des commentaires approuvés par notion ne sont pas retournés car les conditions s'appliquent à l'instruction SQL dans son ensemble et pas seulement à l'association. Vous devez désambiguïser les références de la colonne pour que cela se produise, par exemple: order => "author.name DESC" fonctionnera mais: order => "name DESC" ne fonctionnera pas.

Pour charger désireux lignes filtrées d'une association, utiliser une association avec des conditions:

class Post < ActiveRecord::Base 
    has_many :approved_comments, :class_name => 'Comment', 
      :conditions => ['approved = ?', true] 
end 

Post.find(:all, :include => :approved_comments) 
+0

Merci pour la plus excellente écriture-up, lien et explication, KandadaBoggu! Cela m'a certainement mis sur la bonne voie, j'ai toujours un problème avec self.categories.includes (: children =>: published_pages,: published_pages) fournissant aux parents sans pages ou catégories d'enfants avec des pages. MERCI ENCORE! – TMB

+0

Mettez à jour votre question et spécifiez votre besoin de présence/absence de pages. –

+0

Merci énormément utile - tirait mes cheveux – jpwynn