ActiveRecord如何调用' where'?

时间:2017-04-26 12:18:26

标签: ruby-on-rails ruby activerecord activesupport

你能不能让我知道Active Record如何调用'哪里有'当我执行User.where(id: 1)

我正在检查Active Record的功能以阅读源代码并通过pry停止进程。 我可以看到当我执行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

'其中'被委派给:全部。 因此,它去了 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)?

1 个答案:

答案 0 :(得分:4)

  

我不明白这一部分。为何选择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_scopedUser::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答案的范围。