当查询使用包含时,Rails如何处理has_many? [英] How does Rails handle a has_many when query uses includes?

查看:277
本文介绍了当查询使用包含时,Rails如何处理has_many?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有一个有多个帖子的用户模型,在下面的情况下,Rails对数据库执行多少查询?

  class User 
has_many:posts

#这是主要的方法...
def has_posted?
posts.any? {| p | posted? }
end
end

#有一个attrposted,它是一个布尔
类Post
belongs_to:user
end


#一些控制器
用户= User.includes(:posts).all


#视图中的
< %users.each do | user | %>
<%='posted!'if user.has_posted? %>
<%end%>

我使用的事实包括在初始查询中做任何魔术,当我循环在 has_posted?方法中的返回的帖子,以防止对每个用户的posts表的多个查找

解决方案


我在使用的事实包括在初始查询中做任何魔术,当我循环返回的帖子在has_posted?方法以防止对每个用户的posts表进行多次查找?


是的。



如果你不使用 .includes(),你将有一个N + 1查询。也就是说必须查找第一个项目和N更多之后。使用 .includes()会在执行时期间将post对象加​​载到内存中。执行时间将在您调用执行查询的点...在您的示例中使用 has_posted?方法,执行点将是



但是,这里有一个更好的方法来做到这一点!即使用数据库查询,而不是通过使用ruby循环遍历一组帖子。所以像这样:

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

类Post
范围:is_posted, - > {where(posted:true)}
end

仅选择将已发布设置为true的帖子。然后 .any?会将查询转换为COUNT个查询,瞧! (在控制台上运行此命令,并观察每种方法生成的查询。)


If I have a User model that has many Posts, how many queries will Rails perform against the database in the following scenario?

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 %>

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?

解决方案

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?

Yes.

If you don't use the .includes() you'll have what's called an N+1 query. I.e. having to look up the first item and N more after it. Using .includes() will eager load the post objects into memory at execution time. Execution time will be at the point you call something that executes the query... In your example with the has_posted? method, the execution point would be posts.any?.

UPDATE

However,here's an even better way to do this! i.e. with a database query instead of by looping through a collection of posts with ruby. So like this:

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

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

In this fashion, you get the database to only select those posts that have posted set to true. And then the .any? will turn the query into a COUNT query and voila! (Run this on the console and watch the queries generated by each approach.)

这篇关于当查询使用包含时,Rails如何处理has_many?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆