Rails 3 - 有条件的预加载

发布于 2024-10-02 09:11:34 字数 1655 浏览 2 评论 0原文

好吧,我完全被这个问题难住了。我正在尝试建立一个按类别组织的已发布网页的菜单。

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

(self是@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_pa​​ges,没有带有已发布页面的子类别)。一个例子:

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

我的临时修复是在查询后附加:

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

再次感谢您的帮助。

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

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

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:

(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.

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)

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?}

Thanks again for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

鹿! 2024-10-09 09:11:34

添加一个名为 published_pa​​ges 的新关联(除了您当前的关联)

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 文档(在急切加载关联之后滚动 10-15 行部分)。我已在下面包含相关片段:

例如

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

这将产生一个带有如下连接的 SQL 查询:

LEFT OUTER JOIN 评论 ON comments.post_id = posts.id 和 
左外连接作者在authors.id = posts.author_id。 

请注意,使用这样的条件可能会产生意想不到的后果。
在上面的示例帖子中,带有概念批准的评论不会被返回
根本没有,因为条件适用于整个 SQL 语句
不仅仅是协会。您必须消除列的歧义
发生此回退的参考,例如:order =>
"author.name DESC" 可以工作,但是 :order => “name DESC”不会。

要预先加载关联的筛选行,请使用带条件的关联:

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

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

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)

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:

For example

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

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. 

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文