我是一名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
这种巫术是如何运作的?
答案 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.inspect
为1
。魔法!同样适用于"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