Rails的ActiveRecord链“哪里”子句没有多个查询?
我是一个学习Ruby on Rails的awseomness的PHP开发人员,我喜欢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
这个巫术是如何工作的?
where
方法返回一个ActiveRecord::Relation
对象,并且它本身不会发出数据库查询。 这是你使用这个重要的对象的地方 。
在控制台中,你可能是这样做的:
@person = Person.where(name: "Jason")
然后blammo它发出一个数据库查询,并返回似乎是一个名为贾森每个人的数组。 耶,活动logging!
但是,你做这样的事情:
@person = Person.where(name: "Jason").where(age: 26)
然后发出另一个查询,但是这个对于被称为Jason的人来说是26个。但是它只发出一个查询,所以另一个查询去了哪里呢?
正如其他人所说,这是因为where
方法返回一个代理对象。 它实际上并不执行查询并返回数据集,除非被要求这样做。
当你在控制台上运行任何东西的时候,它会输出你运行的任何结果的检查版本。 如果你把1
放在控制台中,然后回车,你会得到1
因为1.inspect
是1
。 魔法! "1"
。 其他各种各样的objets没有定义一个inspect
方法,所以Ruby会回落到Object
,它会返回一些可怕的东西,如<Object#23adbf42560>
。
每一个ActiveRecord::Relation
对象都有一个定义的inspect
方法,以便它可以引起一个查询。 当您在控制台中写入查询时,IRB将调用对该查询的返回值的inspect
,并输出几乎人类可读的内容,如您将看到的Array。
如果你只是在一个标准的Ruby脚本中发布这个脚本,那么在对象被检查(通过inspect
)或迭代使用each
脚本之前,不会执行任何查询,或者to_a
调用to_a
方法。
直到发生这三件事情中的一件,你可以链接尽可能多的语句,然后当你调用inspect
, to_a
或者each
时,它将最终执行那个查询。
有一些被称为“kickers”的方法实际上是将查询引发到数据库。 在此之前,他们只是创build一个曾经踢过的AST节点,会生成实际的SQL(或正在编译的语言)并运行查询。
看到这个博客文章的更深入的解释如何做到这一点。
您可以阅读代码,但这里有一个概念是代理模式。
@person可能不是真正的对象,而是这个对象的代理,当你需要一些属性时,活动logging最终执行查询。 Hibernate有相同的概念。
- 如何将activerecord结果转换为散列数组
- Rails 3的devise,current_user不能在模型中访问?
- 在Rails中复制模型实例
- 如何在RSpectesting中打开ActiveRecord的SQLdebugging日志logging?
- 如何在Arel和Rails中做一个LIKE查询?
- Rails:为什么find(id)在rails中引发exception?
- 在Rails中单独的date和时间表单字段
- 如何在Ruby on Rails中实现Active Recordinheritance?
- Ruby on Rails。 如何在一个:属于关系中使用Active Record .build方法?