这个ruby / rails构造总是困惑我:
User.where(:name => "Thiago").limit(3).using(:slave_one)
这必须从左到右执行,以便每次连续调用都有一个接收器。所以我们从User类开始,在其上调用where
,返回ActiveRecord::Relation
的实例。然后在该实例上调用limit
,返回另一个ActiveRecord::Relation
实例。然后在该实例上调用using
(恰好选择一个分片)。我想,整个事情在ActiveRecord::Relation
对象内建立了一个SQL查询。我的问题是,“是什么触发了查询的实际执行”?它不能在链中的任何特定点执行,因为链中可能存在进一步修改查询的后继者。即使在using
返回之后,查询仍然无法执行,因为它无法知道是否将其他方法添加到链中。显然,它在构建之后会执行查询,那么查询实际上是如何调用的?
谢谢......我现在看到链中方法的名称有“语义”。有些人会进一步修改正在构建的查询。最后一个也可能是最后一个可能是需要提取数据的类型。
答案 0 :(得分:7)
在您询问某些数据之前,ActiveRecord :: Relation不会打扰与数据库交谈。例如:
User.where(:name => "Thiago").limit(3).using(:slave_one).count
# talks to the database here ----------------------------^^^^^
如果你看一下ActiveRecord :: Relation,你会看到它包含ActiveRecord::QueryMethods,其中的大部分内容都是这样的:
def x(*args)
relation = clone
# merge args into relation
relation
end
所以Relation只是逐个构建一个查询,直到你做了一些需要执行查询的事情;然后它将构建适当的SQL,将其发送到数据库,并对数据库发回的内容做一些有用的(理论上)。
另请注意,每个QueryMethods方法都会返回克隆和修改的关系,因此您可以执行以下操作:
r1 = User.where(:name => 'Pancakes')
r2 = r1.limit(3)
然后使用r1
抓取所有匹配或r2
以抓取其中的三个。
答案 1 :(得分:3)
这个构造(在你构建它时查询永远不会执行)是故意的。它叫做Lazy Loading。
当您第一次向关系询问数据时,查询会执行。 IE如果你有:
@users = User.where(:name => "Thiago").limit(3).using(:slave_one)
@users.first.name #the query executes here
通常这是在视图模板中第一行调用查询数据时执行的。