渴望加载:正确的做事方式

我正在运行Ruby on Rails 3.1。 我阅读了以下关于急切加载的文章和文档,我想找到一个正确的方法来做事:

  1. 渴望加载协会 [官方文档]
  2. ActiveRecord :: Associations :: ClassMethods (参见“渴望加载关联”一节)[官方文档]
  3. 渴望加载 [博客文章]

#2说:

请注意,使用Post.includes([:author,:comments])等条件,其中([‘comments.approved =?’,true])。all都会产生意想不到的后果。

#3表示那些意想不到的后果是( 注意 :示例非常相似所以我引用了博客文章的确切文本,但你必须记住解决方法,而不是具体的实现):

此查询,因为它将使用LEFT JOIN,也会丢弃所有post,而不会在其任何评论上添加带有“first”字样的评论。

也就是说,如果存在非“关联”对象,则不会加载“主关联”对象。 当我尝试通过在我之前的问题中 添加诸如.where(:category_relationships => {:user_id => @current_user.id}) 条件来尝试使用预先加载时会发生这种情况,但我不希望这种情况发生。

所以(失败者因为我可能无法在我的情况下使用急切加载,其中条件无法在has_many语句中设置 – 请注意,在上面的代码中, @current_user.id是“动态设置”,与上述网站中的示例不同) , 我想知道是否有pratiques /技术/策略以限制数据库查询,因为我有一个“N + 1问题”

也许这些pratiques /技术/策略可以通过使用Ruby on Rails框架来实现…… #1说:

即使Active Record允许您像加入一样指定热切加载关联的条件,但推荐的方法是使用联接。

什么以及如何以正确的方式解决这个问题?


也许解决方案是通过运行特定的和分离的数据库查询来检索和构建自己需要加载的内容,但问题是如何“检索”/“关联”/“插入”那些检索到的“关联”对象到“主要相关的“对象,以便那些可以使用”一个là急切加载“的方式? 也就是说,如何使用@article.comments类的代码(参见上述问题以获取更多信息)并获得我自己急于加载的评论? 在急切加载之后,是否有可能 / 正确地制作类似@article.comments = my_eager_loaded_comments以便“传递”/“关联”/“插入”评论到文章?

在我急切加载之后,是否有可能/正确地制作类似@ 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 

在由上述方法返回的文章集合中,评论关联将仅具有该特定用户的评论。

我希望这就是你所要求的。

来自#2 ActiveRecord :: Associations :: ClassMethods来自:

如果您确实只想加载一个关联的某些成员,那么通常更自然地包含一个在其上定义条件的关联:

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

这将加载post并急切加载approved_comments关联,该关联仅包含已批准的评论。

如果我在上下文中正确理解了这一点,那么当您使用includes()将.where()应用于主查询时会出现歧义,并且AR会将整个查询的位置应用于将主要结果限制为具有合格关联谓词的查询。 但是,如果您将谓词范围仅限于上述关联,则AR会理解并提供所有主要结果以及与其谓词条件匹配的相关对象。