渴望在Rails中的ActiveModel实例上加载关联

aus*_*nbv 12 activerecord lazy-loading ruby-on-rails eager-loading

在RoR中,新人加载类和这样的分区是很常见的错误#解决方案是急切负载

# The bellow generates an insane amount of queries
# post has many comments
# If you have 10 posts with 5 comments each
# this will run 11 queries 
posts = Post.find(:all)
posts.each do |post|
  post.comments
end
Run Code Online (Sandbox Code Playgroud)

渴望加载的解决方案非常简单

# should be 2 queries
# no matter how many posts you have
posts = Post.find(:all, :include => :comments) # runs a query to get all the comments for all the posts
posts.each do |post|
  post.comments # runs a query to get the comments for that post
end
Run Code Online (Sandbox Code Playgroud)

但是,如果您无法访问类方法,并且只能访问实例方法的集合,那该怎么办呢?

然后你就陷入了查询密集型延迟加载.

有没有办法最小化查询以从实例comments集合中获取所有posts集合?

添加答案(也添加到上面的代码中)


因此,对于我在rdoc中看到的对于rails的热切加载是对ActiveRecord :: Associations的任何扩展的类方法,问题是你没有能力使用类方法,所以你需要使用某种实例方法

我认为它会是什么样的代码示例

post = Posts.find(:all)
posts.get_all(:comments) # runs the query to build comments into each post without the class method.
Run Code Online (Sandbox Code Playgroud)

Fre*_*ung 25

在Rails 3.0及更早版本中,您可以:

Post.send :preload_associations, posts, :comments
Run Code Online (Sandbox Code Playgroud)

您可以传递关联名称的数组或哈希,就像您可以包括:

Post.send :preload_associations, posts, :comments => :users
Run Code Online (Sandbox Code Playgroud)

在Rails 3.1中,这已被移动,您使用Preloader如下:

ActiveRecord::Associations::Preloader.new(posts, :comments).run()
Run Code Online (Sandbox Code Playgroud)

从Rails 4开始,它的调用已经改为:

ActiveRecord::Associations::Preloader.new.preload(posts, :comments)
Run Code Online (Sandbox Code Playgroud)

  • 在rails 4中,人们可以这样做:`ActiveRecord :: Associations :: Preloader.new.preload(posts,:comments)` (2认同)
  • 使用ActiveRecord :: Associations :: Preloader是否有任何弊端? (2认同)
  • 多年来,@ swap.nil api发生了一些变化,但除此之外,我多年来一直在生产中使用它。 (2认同)