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

Bac*_*cko 20 ruby database ruby-on-rails eager-loading ruby-on-rails-3

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

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

#2说:

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

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

此查询,因为它将使用LEFT JOIN,也会丢弃所有帖子,而不会在其任何评论上添加带有"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这样的内容"传递"/"关联"/"插入"评论到文章?

Anj*_*jan 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
Run Code Online (Sandbox Code Playgroud)

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

我希望这就是你要求的.


dbe*_*hur 2

来自 #2 ActiveRecord::Associations::ClassMethods 的内容如下:

如果您确实希望只加载关联的某些成员,那么通常更自然的是包含一个定义了条件的关联:

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

Post.includes(:approved_comments)
Run Code Online (Sandbox Code Playgroud)

这将加载帖子并立即加载已批准的评论关联,该关联仅包含已批准的评论。

如果我在上下文中正确理解这一点,那么当您将 .where() 应用于包含 () 的主查询时,就会存在歧义,而 AR 将 where 应用于整个查询,将您的主要结果限制为那些具有限定关联谓词的结果。但是,如果您将谓词范围限定为上述关联,AR 就会理解并为您提供所有原则结果以及与其谓词条件相匹配的关联对象。

  • 我不能像你写的那样使用 `has_many` 关联,因为在我的情况下,我应该声明类似 `has_many, :conditions =&gt; ['user_id = ?', @current_user.id]` (*这是不可能的!* 。 ..当然据我所知)。所以我想知道与急切加载功能相关的该问题的解决方案。 (3认同)