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

时间:2012-05-25 00:40:44

标签: ruby-on-rails activerecord

我是一名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

这种巫术是如何运作的?

4 个答案:

答案 0 :(得分:141)

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

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

@person = Person.where(name: "Jason")

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

但是你做了这样的事情:

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

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


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

当您在控制台中运行任何时,它将输出您所运行的任何结果的检查版本。如果您将1放入控制台并按Enter键,则会1返回,因为1.inspect1。魔法!同样适用于"1"。各种其他对象没有定义inspect方法,所以Ruby回到Object上的那个,它返回像<Object#23adbf42560>一样的 ghastly 。< / p>

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


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

直到这三件事中的一件发生,您可以根据需要链接尽可能多的to_a语句,然后当您时调用where,{{ 1}}或inspect,然后它将最终执行该查询。

答案 1 :(得分:7)

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

有关如何完成此操作的详细说明,请参阅this blog post

答案 2 :(得分:4)

您可以阅读代码,但这里的一个概念是代理模式。

可能@person不是真正的对象,而是该对象的代理,当您需要某些属性时,活动记录最终会执行查询。 Hibernate有相同的概念。

答案 3 :(得分:-2)

也许有点太晚但你可以使用哈希:

@person = Person.where({name: "Jason", age: 26})

结果查询:

SELECT "person".* FROM "person"  WHERE "person"."name" = 'Jason' AND "person"."age" = 26