什么时候执行 ActiveRecord 查询?

bil*_*lal 5 ruby ruby-on-rails ruby-on-rails-3

我对 Ruby 如何执行查询感到困惑:

假设我们有两种方法:

def meet1
   user = User.all
end
Run Code Online (Sandbox Code Playgroud)

每次我调用这个方法时,我都会运行一个查询,它说:

'用户负载 (18.3ms) SELECT "users".* FROM "users" INNER JOIN "roles" ON "roles"."user_id" = "users"."id" WHERE "users"."banned" = 'f' AND "roles"."description" = 'gogetter''

这意味着它查询用户...

假设我有另一种方法:

def meet2
  user = User.all
  user.to_sql
end
Run Code Online (Sandbox Code Playgroud)

当我调用它时,它返回了该查询的 SQL 格式:

所以我的问题是在第一种方法中执行查询,但是查询是否在第二种方法中执行?或者它只是向我显示最终结果而不执行查询,因为我从未使用过它?

Phl*_*lip 7

user = User.all除了创建一个潜在的查询并将spawn其副本复制到user. 这遵循“构建器模式”;user然后可以说user.joins(...), 或user.order(...), 来构建不同的潜在查询。它们都返回spawn查询的编辑副本。

您所做的操作meet1会触发对数据库的实际命中。我怀疑像p meet1,甚至是你的 IRB shell 这样无害的东西,可以将spawned 潜在数据库查询评估为Enumeration,然后访问数据库。


Man*_*shh 5

我也想让你看看这个答案

当您调用User.all它时,它会返回User::ActiveRecord_Relation对象,并且该对象本身不会发出数据库查询。重要的是你在哪里使用这个对象。

因此,当调用 meet1 时,它会发出查询,但如果出现meet2 User.all关系对象问题,则会user.to_sql发出与数据库相关的查询。

当您尝试根据条件链接多个过滤器时,您可以看到同样的事情发生

u = User.all
u = u.where(name: "Hello") if any_condition?
u = u.where(last_name: 'world') if any_other_condition?
Run Code Online (Sandbox Code Playgroud)

在这种情况下 in any_condition? 还有任何其他条件吗?是的,它只执行一个查询,合并所有 3 件事 .all 和所有 where 条件。

我希望您看看这里的博客,它展示了一些kickers方法,这将使您更清楚地了解该方法。

  • 一个潜在的混乱点 - 如果您在 irb 或 Rails 控制台中运行此代码,则在每一行之后,rails 控制台将尝试评估结果,从而导致其执行。 (3认同)