【问题标题】:How ActiveRecord calls 'where'?ActiveRecord 如何调用“where”?
【发布时间】:2017-04-26 12:18:25
【问题描述】:

您能否告诉我当我执行User.where(id: 1) 时 Active Record 是如何调用“where”的?

我正在检查 Active Record 的功能以读取源代码并通过撬动来停止进程。 我可以看到当我执行User.where(id: 1) 时,进程转到 rails/activerecord/lib/active_record/querying.rb

delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
         :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly,
         :having, :create_with, :distinct, :references, :none, :unscope, :merge, to: :all

'where' 委托给 :all。 因此它去 rails/activerecord/lib/active_record/scoping/named.rb

def all
  if current_scope
   current_scope.clone
  else
    default_scoped
  end
end

我不明白这部分。为什么它适用于所有人? 委托可以设置为类方法吗?我虽然可以委托给类变量、实例变量。

在 scoping/named.rb all 方法中的 default_scope 之后,进程转到rails/activerecord/lib/active_record/relation/query_methods.rb

def where(opts = :chain, *rest)
  if :chain == opts
    WhereChain.new(spawn)
  elsif opts.blank?
    self
  else
    spawn.where!(opts, *rest)
  end
end

为什么? where 不是委托给:all 吗?它如何回到where(relation/query_methods.rb)?

【问题讨论】:

  • 出于好奇,你为什么关心where方法的实现?
  • 出于好奇,你为什么关心咖啡人为什么关心where方法的实现?
  • 出于好奇,你为什么关心MrDanA为什么关心我为什么关心where方法的实现? :)
  • (蝙蝠侠的声音)MrDana 关心的不是你的定义。但是当TomLord 关心CoffeeMan 的时候,你怎么关心它!
  • @bkunzi01 我喜欢。

标签: ruby-on-rails ruby activerecord activesupport


【解决方案1】:

我不明白这部分。为什么会转到all

因为:

User.where(id: 1)

相当于:

User.all.where(id: 1)

这个委托是为了简化 API,在没有显式调用时添加对 all 的隐式调用。

它如何返回到where (relation/query_methods.rb)?

请记住,这是一个代表团,而不是别名。所以,因为:

User.all

返回:

User.default_scoped

这意味着,实际上,这是正在构建的方法链:

User.where
--> User.all.where
--> User.default_scoped.where

而且由于User.default_scoped是一个User::ActiveRecord_Relation对象,它对#where的定义确实是在rails/activerecord/lib/active_record/relation/query_methods.rb中定义的,如下:

def where(opts = :chain, *rest)
  if :chain == opts
    WhereChain.new(spawn)
  elsif opts.blank?
    self
  else
    spawn.where!(opts, *rest)
  end
end

...但这只是故事的开始。我们距离为查询构造实际的 SQL 还有很长的路要走。

Here is a series of blog posts 如果您有兴趣,请深入了解 - 但我认为这超出了单个 StackOverflow 答案的范围。

【讨论】:

  • 感谢您的回答。我可以知道为什么User.where -> User.all.where吗?是的,正如您所指出的,我认为委托就像别名。基于此document 委托到:选项指定目标对象。 : 一切都是对象?它看起来像类方法。我仍然无法理解系统如何链接User.all.where之类的方法不是因为delegate吗?我应该检查另一部分吗?
  • 请记住,在 ruby​​ 中,everything 是一个对象。甚至方法也是对象(ruby-doc.org/core/Method.html)!!!与其纠结于“对象”这个词,不如把它想象成“将where 委托给all 的响应”,或者换句话说User.where == User.all.where
  • 这当然不同于别名。如果这是一个别名,而不是一个委托,那么它确实是User.where == User.all。但这里不是这样。
猜你喜欢
  • 2014-10-23
  • 1970-01-01
  • 1970-01-01
  • 2015-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-08
  • 1970-01-01
相关资源
最近更新 更多