.where(nil) 和 .all 之间有什么区别?

Sco*_*aux 5 ruby ruby-on-rails where-clause

我一直在使用

产品.全部
但我看到的很多代码都在使用
产品.where(nil)
填充变量时。这个网站有一个我发现的使用 where(nil) 的示例。我搜索了文档,发现 where(nil) 替换了scoped,但无法弄清楚它的作用。

rmc*_*rry 2

我相信过去是有区别的,但从 Rails 4 开始就不再有了。这是因为 Rails 4.all返回一个关系,而过去它返回一个数组。所以之前:

Product.all
Run Code Online (Sandbox Code Playgroud)

立即向数据库发起查询以返回所有记录,这些记录将被加载到内存中的数组中。基本上你是在告诉 Rails 你现在就想要数据。请参阅此问题以获取更多信息。

Product.where(nil) 
Run Code Online (Sandbox Code Playgroud)

创建一个查询(实际上是一个返回 的匿名范围ActiveRecord:Relation)。

仅当您尝试访问查询的数据时,该查询才会执行。由于它是一个作用域,因此您可以链接其他作用域(无需每次都访问数据库),并在访问数据时将整个链作为一个查询执行。

在问题中链接的 Justin Weiss 文章中,我们看到以下代码:

def index
  @products = Product.where(nil) # creates an anonymous scope
  @products = @products.status(params[:status]) if params[:status].present?
  @products = @products.location(params[:location]) if params[:location].present?
  @products = @products.starts_with(params[:starts_with]) if params[:starts_with].present?
end
Run Code Online (Sandbox Code Playgroud)

当索引方法结束并返回数据时,该代码将执行一个数据库调用。

但如果你将第一行更改为:

@products = Product.all
Run Code Online (Sandbox Code Playgroud)

该查询将立即执行。然后添加范围,当索引方法结束时将触发另一个查询。这样效率比较低。

编辑

我相信当您第一次尝试访问 @products 中的某些数据时(而不是索引方法结束时),数据库调用实际上会发生。例如。如果您执行@products.first,则查询将执行。