ActiveRecord查询链

lyd*_*ues 3 ruby activerecord ruby-on-rails active-record-query rails-activerecord

这个ruby/rails构造总让我困惑:

User.where(:name => "Thiago").limit(3).using(:slave_one)
Run Code Online (Sandbox Code Playgroud)

这必须从左到右执行,以便每次连续调用都有一个接收器.所以我们从User类开始,where在它上面调用它返回一个实例ActiveRecord::Relation.然后limit在该实例上调用,返回另一个实例ActiveRecord::Relation.然后using在该实例上调用(恰好选择一个分片).ActiveRecord::Relation我想,整个事情在一个对象内建立一个SQL查询.我的问题是,"是什么触发了查询的实际执行"?它不能在链中的任何特定点执行,因为链中可能存在进一步修改查询的后继者.即使在using返回之后,查询仍然无法执行,因为它无法知道是否将其他方法添加到链上.显然,它在构建之后会执行查询,那么查询是如何实际调用的呢?


谢谢......我现在看到链中方法的名称有"语义".有些人会进一步修改正在构建的查询.最后一个也可能是最后一个可能是需要获取数据的类型.

mu *_*ort 7

在您询问某些数据之前,ActiveRecord :: Relation不会打扰与数据库通信.例如:

User.where(:name => "Thiago").limit(3).using(:slave_one).count
# talks to the database here ----------------------------^^^^^
Run Code Online (Sandbox Code Playgroud)

如果你看看ActiveRecord :: Relation,你会看到它包含ActiveRecord :: QueryMethods,其中大部分内容如下所示:

def x(*args)
  relation = clone
  # merge args into relation
  relation
end
Run Code Online (Sandbox Code Playgroud)

所以Relation只是逐个构建一个查询,直到你做了一些需要执行查询的事情; 然后它将构建适当的SQL,将其发送到数据库,并对数据库发回的内容做一些有用的(理论上).

另请注意,每个QueryMethods方法都返回克隆和修改的关系,因此您可以执行以下操作:

r1 = User.where(:name => 'Pancakes')
r2 = r1.limit(3)
Run Code Online (Sandbox Code Playgroud)

然后r1用来抓住所有比赛或者r2只抓住其中的三个.