好的,我对这一点感到非常难过。我正在尝试构建按类别组织的已发布网页菜单。
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
Page模型也有:is_published,所以我也试图对它进行过滤。我不愿意发布我的微弱查询尝试,但除了乞求更聪明的人之外别无其他解决方案:
(自我是@current_website)
self.categories.includes(:children, :pages).where('pages.is_published = 1')
这主要返回我需要的内容,但不返回没有发布页面的父类别。例如,如果我有:
,它会很有效Parent Category
- Published Page
- Child Category
-- Published Page
失败的地方是我在父母中没有已发布的页面,如下所示:
Parent Category
- Child Category
-- Published Page
- Child Category
-- Published Page
提前感谢您提供任何帮助。我正在尽可能多地学习有关查询的内容,但我在这方面已经反对了。
更新:实施KandadaBoggu的建议已经产生了更好的结果,这被添加到Category.rb
has_many :published_pages, :class_name => "Page",
:conditions => {:is_published => true}
但是,使用以下内容时:
self.categories.where(:parent_id => nil).includes({:children => :published_pages},
:published_pages)
我得到了我需要的结果,但我也得到了空的父类别(没有published_pages,没有已发布页面的子类别。例如:
- Parent Category
-- Published Page
- Parent Category
-- NOTHING
我的临时修复是将查询附加到:
reject{|category| category.pages.empty? && category.children.empty?}
再次感谢您的帮助。
答案 0 :(得分:14)
添加一个名为published_pages
的新关联(除了您当前的关联)
class Category
has_many :children, :class_name => "Category",
:foreign_key => "parent_id"
has_many :published_pages, :class_name => "Page",
:conditions => { :is_published => true }
end
现在您可以按如下方式获取所有类别:
self.categories.includes(:children, :published_pages)
如果您有兴趣了解为什么您的方法不起作用,请阅读Rails documentation(在Eager loading of associations
部分后滚动10-15行)。我在下面列出了相关代码:
例如
Post.includes([:author, :comments]).where(['comments.approved = ?', true]).all
这将导致单个SQL查询具有以下行的连接:
LEFT OUTER JOIN comments ON comments.post_id = posts.id and LEFT OUTER JOIN authors ON authors.id = posts.author_id.
请注意,使用此类条件可能会产生意想不到的后果。 在上面的示例中,不会返回带有概念批准注释的帖子 因为条件适用于整个SQL语句 而不仅仅是协会。您必须消除列的歧义 发生此回退的参考,例如:order => “author.name DESC”可以工作但是:order => “名称DESC”不会。
要急切加载过滤的关联行,请使用条件关联:
class Post < ActiveRecord::Base
has_many :approved_comments, :class_name => 'Comment',
:conditions => ['approved = ?', true]
end
Post.find(:all, :include => :approved_comments)