【问题标题】:What is the proper way to eager load associated objects for a 'has_many' association?为“has_many”关联急切加载关联对象的正确方法是什么?
【发布时间】:2014-03-04 16:07:06
【问题描述】:

我正在使用 Ruby on Rails 4,我希望为 has_many 关联加载关联对象。也就是说,我有以下模型:

class Article < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :article
end

由于我在加载articles 时经常检索comments,因此我希望每次搜索articles 时都急切加载comments,例如在这些情况下:

# In these cases the eager loading should happen.
Article.find(1)
Article.where(:title => 'Sample text')
@current_user.articles

处理此问题的正确方法是什么?怎么样?

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 associations eager-loading


    【解决方案1】:

    您应该使用includes 方法,如下所示:

    Article.includes(:comments).where(title: 'Sample text')
    

    对于您的第一种情况,您实际上并不需要预先加载,因为您只选择一条记录,所以这不是 n+1 问题。你可以这样做:

    article = Article.find(1)
    article.comments
    

    如果你经常使用包含你的文章,你可以定义范围:

    scope :with_comments, -> { includes(:comments }
    

    简单地称呼它:

    Article.with_comments.where(title: 'Sample text')
    

    当您想要包含 comments 的关系来自另一个关联时,没有任何变化,您可以同时执行以下操作:

    @current_user.articles.includes(:comments)
    

    @current_user.articles.with_comments
    

    【讨论】:

    • 我应该将includes 语句直接添加到has_many 关联吗?
    • @user502052 不,因为它甚至无法完成您的工作。
    • 当我运行代码时如何解决急切加载:@current_user.articles? - 注意:我更新了问题,因为我忘了添加提到的案例。
    • @user502052 我编辑了我的答案以涵盖您的扩展问题。
    【解决方案2】:

    如果你想让comments在你加载文章时自动加载,你可以在文章模型上使用default_scope

    class Article < ActiveRecord::Base
      has_many :comments
      default_scope :include => :comments
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多