Eager loading: The right way to do things

前端 未结 2 2031
星月不相逢
星月不相逢 2020-12-13 14:59

I am running Ruby on Rails 3.1. I read the following articles and documentations about eager loading and I would like to find a right way to do things:

相关标签:
2条回答
  • 2020-12-13 15:22

    From #2 ActiveRecord::Associations::ClassMethods comes this:

    If you do want eager load only some members of an association it is usually more natural to include an association which has conditions defined on it:

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

    This will load posts and eager load the approved_comments association, which contains only those comments that have been approved.

    If I understand this correctly in context, there's an ambiguity when you apply .where() to your main Query with an includes(), and AR applies the where to the whole query limiting your principle results to those that have qualifying associated predicates. But if you scope the predicate to just the association as above, AR understands and gives you all your principle results and those associated objects which match their predicate condition.

    0 讨论(0)
  • 2020-12-13 15:30

    After my eager loading, is it possible / correct to make something like @article.comments = my_eager_loaded_comments so to "pass"/"associate"/"interpolate" comments to articles?

    Yes, it is possible. I do this regularly.

    Note that my solution still retrieves ALL the associated objects from the DB. I don't think there is any solution to retrieving just the filtered association objects if your condition is dynamic. My solution focuses on the filtering of the retrieved association objects.

    I am assuming the requirement is to get a list of articles and in each article, eager load the comments of only one particular user.

    In the Article model:

    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
    

    In the collection of articles returned by the above method, the comments association will have only the comments of that particular user.

    I hope this is what you are asking for.

    0 讨论(0)
提交回复
热议问题