ruby-on-rails – 当查询使用包含时,Rails如何处理has_many?

如果我有一个包含许多帖子的用户模型,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
<% users.each do |user| %>
  <%= 'posted!' if user.has_posted? %>
<% end %>

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

最佳答案

Does the fact that I’m using includes in the initial query do any magic when I loop over the returned posts in the has_posted? method to prevent multiple lookups against the posts table for each user?

是.

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

UPDATE

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

class User
  def has_posted?
    posts.is_posted.any?
  end
end

class Post
  scope :is_posted, -> { where(posted: true) }
end

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

点赞