当查询使用包含时,Rails如何处理has_many?

如果我有一个包含许多post的用户模型,Rails会在以下场景中对数据库执行多少次查询?

class User has_many :posts # this is the main method in question... def has_posted? posts.any? {|p| p.posted? } end end # has an attr "posted" which is a boolean class Post belongs_to :user end # some controller users = User.includes(:posts).all # in the view    

当我循环遍历has_posted?的返回post时,我在初始查询中使用的事实是否有任何魔力has_posted? 防止每个用户对posts表进行多次查找的方法?

当我循环遍历has_posted中的返回post时,我在初始查询中使用的事实是否有任何魔力? 防止每个用户对posts表进行多次查找的方法?

是。

如果你不使用.includes()你将拥有所谓的N + 1查询。 即不得不查看第一个项目,然后再查看N个项目。 使用.includes()会在执行时急切地将post对象加​​载到内存中。 执行时间将在您调用执行查询的位置…在您的示例中使用has_posted? 方法,执行点将posts.any?

UPDATE

但是,这是一个更好的方法来做到这一点! 即使用数据库查询而不是通过循环使用ruby的post集合。 像这样:

 class User def has_posted? posts.is_posted.any? end end class Post scope :is_posted, -> { where(posted: true) } end 

通过这种方式,您可以使数据库仅选择已posted设置为true的post。 那么.any? 将查询转换为COUNT查询,瞧! (在控制台上运行此命令并观察每种方法生成的查询。)