如何在没有多个查询的情况下将Rails ActiveRecord链接到"where"子句?

Rya*_*yan 69 activerecord ruby-on-rails

我是一名PHP开发人员,学习Ruby on Rails的优点,我喜欢ActiveRecord,我注意到一些非常有趣的东西,这就是ActiveRecord方法检测方法链结束执行查询的方式.

@person = Person.where(name: 'Jason').where(age: 26)

# In my humble imagination I'd think that each where() executes a database query
# But in reality, it doesn't until the last method in the chain
Run Code Online (Sandbox Code Playgroud)

这个巫术是如何运作的?

Rya*_*igg 147

where方法返回一个ActiveRecord::Relation对象,并且该对象本身不会发出数据库查询.这是你使用这个重要的对象的地方.

在控制台中,您可能正在这样做:

@person = Person.where(name: "Jason")
Run Code Online (Sandbox Code Playgroud)

然后blammo它会发出一个数据库查询并返回看起来像是 Jason的每个人的数组.耶,活跃记录!

但是你做了这样的事情:

@person = Person.where(name: "Jason").where(age: 26)
Run Code Online (Sandbox Code Playgroud)

然后发出另一个查询,但是这个人被称为Jason的人是26但是它只发出一个查询,那么另一个查询去哪了?


正如其他人所建议的,这种情况正在发生,因为该where方法返回了一个代理对象.除非要求它执行此操作,否则它实际上不会执行查询并返回数据集.

当您在控制台中运行任何内容时,它将输出所运行的任何内容的结果的检查版本.如果你把1在控制台并回车,你会得到1回来,因为1.inspect1.魔法!同样如此"1".其他各种对象不具有inspect定义的方法,并因此Ruby回落到上一个Object返回的东西可怕的喜欢<Object#23adbf42560>.

每个ActiveRecord::Relation对象都有inspect定义的方法,因此它会导致查询.当您在控制台中编写查询时,IRB将调用inspect该查询的返回值并输出几乎人类可读的内容,例如您将看到的数组.


如果你只是在一个标准的Ruby脚本中发布它,那么在对象被检查(通过inspect)或通过使用迭代each或者to_a调用它的方法之前不会执行任何查询.

直到这三种情况之一发生,你可以链尽可能多的where就可以了报表,你会喜欢的,然后当你打电话inspect,to_aeach在其上,那么它最终将执行该查询.

  • 相关[Railscast](http://railscasts.com/episodes/239-activerecord-relation-walkthrough)用Rails源代码解释它。 (2认同)

x1a*_*1a4 7

有许多方法被称为"踢球者",实际上是将查询发送到数据库.在此之前,他们只创建AST节点,这些节点曾经踢过,将生成实际的SQL(或编译为的语言)并运行查询.

有关如何完成此操作的详细说明,请参阅此博客文章.