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

时间:2011-12-17 20:30:35

标签: ruby-on-rails activerecord lazy-loading 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

解决方案很容易加载

# 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

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

然后你会遇到查询密集型延迟加载。

有没有办法最小化查询以从实例集合中获取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.

3 个答案:

答案 0 :(得分:24)

在Rails 3.0及更早版本中,你可以这样做:

Post.send :preload_associations, posts, :comments

您可以传递关联名称的数组或哈希值,例如:

Post.send :preload_associations, posts, :comments => :users

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

ActiveRecord::Associations::Preloader.new(posts, :comments).run()

自从Rails 4以来,它的调用已经改为:

ActiveRecord::Associations::Preloader.new.preload(posts, :comments)

答案 1 :(得分:0)

我想我得到你所要求的。

但是,我认为您不必担心您可以访问哪些方法。外键关系(以及ActiveRecord关联,例如has_manybelongs_to等)将负责确定如何加载相关记录。

如果你能提供一个你认为应该发生的事情的具体例子,以及的实际代码,你会更容易看到你所得到的。

答案 2 :(得分:0)

您是如何获得模型实例的集合,以及您使用的是哪个版本的Rails?

您是说您完全无法访问控制器或模型本身吗?

给你最好的答案取决于了解这些事情。