2012-03-10 45 views
19

我正在运行Ruby on Rails 3.1。我阅读下面的文章和文档有关预先加载,我想找个做的事情正确的方法:渴望加载:正确的做事方式

  1. Eager Loading Associations【官方文档】
  2. ActiveRecord::Associations::ClassMethods(请参见“联想的预先加载” )【官方文档】
  3. Eager loading [博客文章]

#2说:

注意使用条件像Post.includes([:作者:评论])。其中([ '?comments.approved =',真])所有可以产生意想不到的后果。

#3说,这些意想不到的后果是:(:例子是很相同的,所以我引用的博客文章的确切内容,但你必须记住具体的解决办法,而不是执行):

这个查询,因为它会使用一个LEFT JOIN,所以也会放弃所有没有任何评论的单词“first”的评论。

也就是说,如果存在非“关联”对象,则“主关联”对象将不会被加载。当我尝试使用加入一些条件.where(:category_relationships => {:user_id => @current_user.id})在我的previous question时,会发生这种情况,但我不希望发生这种情况。

所以(失败主义者,因为我可能不能在我的情况下条件不能在has_many语句设置使用预先加载 - 请注意,在上面的代码@current_user.id是存在于例子“动态设置”不像我想知道是否有pratiques /技术/战略,以限制数据库查询,因为我有一个“N + 1问题”

也许这些pratiques /技术/策略是通过使用Ruby on Rails框架的所有可执行...的#1说:

即使活动记录可以让你在渴望 指定条件像加入一样加载关联,推荐的方法是使用 连接。

什么和如何解决这个问题的正确方法?


可能的解决方案是检索和建立自己需要运行特定分离数据库查询装载什么,但随后的问题就如何“通” /“副” /“插值”那些将“关联”对象检索到“主要关联”对象,以便那些可以使用“一种渴望加载”的方式?也就是说,如何使可能(请参阅mentioned question获取更多信息)使用类似@article.comments之类的代码,并只获得我渴望加载自己的评论? 我的渴望加载,是否可能/正确使类似@article.comments = my_eager_loaded_comments这样“传递”/“关联”/“插值”评论文章?

回答

2

从#2 ActiveRecord::Associations::ClassMethods谈到这一点:

如果你想急于负荷只有一个协会的一些成员是 通常更自然包括上定义条件 关联:

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

Post.includes(:approved_comments) 

这将加载信息,并渴望负荷approved_comments协会, 其中包含3个只有那些已被批准的评论。

如果我理解这个正确的情况下,有一个不确定性,当你申请。凡()到主查询与包括()和AR的地方适用于整个查询限制你的原则,结果那些有合格的关联谓词。但是,如果您将谓词的范围仅限于上述关联,那么AR理解并给出所有原则结果以及与谓词条件相匹配的相关对象。

+3

因为在我的情况下,我不能使用'has_many'关联,因为在我的情况下,我应该说''has_many,:conditions => ['user_id =?',@ current_user.id]'(*这是不可能的!* ...当然是我的知识)。因此,我想知道有关急切加载功能的解决方案。 – Backo 2012-03-12 23:54:04

6

我渴望加载后,是有可能的/正确的做出像@ article.comments = my_eager_loaded_comments所以要“通” /“副” /“插值”评论文章?

是的,这是可能的。我经常这样做。

请注意,我的解决方案仍然从数据库中检索所有关联的对象。如果条件是动态的,我认为没有任何解决方法可以检索过滤的关联对象。我的解决方案关注于检索的关联对象的过滤。

我假设的要求是get a list of articles和每篇文章eager load the comments of only one particular user

Article模式:

def self.get_articles_with_comments_of_user(article_ids, user_id) 
    articles = Article.where(id: article_ids).includes(:comments) 

    articles.each do |article| 
    filtered_comments = article.comments.select { |comment| comment.user_id == user_id } 
    article.association("comments").target = filtered_comments 
    end 

    articles 
end 

在通过上述方法返回文章收藏,评论协会将有特定用户的唯一的意见。

我希望这是你要求的。

+0

“如果条件是动态的,我认为没有任何解决方案可以检索过滤的关联对象。” - 也许[这](http://stackoverflow.com/a/15543228/867305)是解决方案? – thejaz 2013-03-21 09:24:23

+0

在链接的答案中,我没有看到任何动态条件传递过滤急切加载。我可能会理解错误。这个答案只是描述了一个普通的'has_many:through'关联。在这个问题的背景下如何使用这个解决方案? – Anjan 2013-03-22 06:49:38