Rails 3-有条件的渴望加载 [英] Rails 3 - Eager loading with conditions

查看:64
本文介绍了Rails 3-有条件的渴望加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,我对此完全感到困惑.我正在尝试构建按类别组织的已发布网页菜单.

Okay, I'm thoroughly stumped on this one. I'm trying to build a menu of published web pages organized by category.

Category.rb:

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,因此我也尝试对其进行过滤.我不愿意发布微弱的查询尝试,但是除了乞求更聪明的人之外,没有其他解决方案:

The Page model also has :is_published, so I'm trying to filter on that as well. I am reluctant to post my feeble query attempts, but see no other solution than to beg much smarter people:

(自身为@current_website)

(self is @current_website)

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

这大部分返回我需要的内容,但没有返回已发布页面的父类别".例如,如果我有以下方法,它会很好用:

This returns mostly what I need, but not Parent Categories without published pages. For instance, it works great if I have:

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

失败的地方是当我在父级中没有已发布的页面时,

Where it fails is when I have no published pages in the parent, like this:

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

在此先感谢您的帮助.我正在努力学习有关查询的尽可能多的知识,但是我对此持反对态度.

Thanks in advance for any help on this. I'm trying to learn as much as I can about queries, but I'm against the wall on this.

更新:实施KandadaBoggu的建议产生了更好的结果,已将其添加到Category.rb

UPDATE: Implementing KandadaBoggu's suggestion has yielded much better results, this was added to Category.rb

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

但是,使用以下内容时:

However, when using the following:

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

我得到了所需的结果,但是我也得到了空的父类别"(没有"published_pa​​ges",没有包含已发布页面的子类别.例如:

I get the results I need, but I also get empty Parent Categories (no published_pages, no child categories with published pages. An example:

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

我的临时解决方法是在查询后附加:

My temporary fix was to appended the query with:

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

再次感谢您的帮助.

推荐答案

添加一个名为published_pages的新关联(除了当前的关联之外)

Add a new association called published_pages (apart from your current associations)

class Category

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

end

现在您可以获取以下所有类别:

Now you can get all the categories as follows:

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

如果您有兴趣了解为什么您的方法行不通,请阅读Rails 文档(在Eager loading of associations部分后滚动10-15行).我在下面添加了相关代码段:

If you are interested in learning why your approach didnt work, read the Rails documentation (scroll 10-15 lines after the Eager loading of associations section). I have included the relevant snippet below:

例如

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

这将导致单个SQL查询,并带有以下类似的联接:

This will result in a single SQL query with joins along the lines of:

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 =>"name DESC"将不起作用.

Note that using conditions like this can have unintended consequences. In the above example posts with notion approved comments are not returned at all, because the conditions apply to the SQL statement as a whole and not just to the association. You must disambiguate column references for this fallback to happen, for example :order => "author.name DESC" will work but :order => "name DESC" will not.

要急于加载关联的过滤行,请对条件使用关联:

To eager load filtered rows of an association, use an association with conditions:

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

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

这篇关于Rails 3-有条件的渴望加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆