ActiveRecord 如何调用 'where'?
How ActiveRecord calls 'where'?
你能告诉我 Active Record 在我执行 User.where(id: 1)
时如何调用 'where' 吗?
我正在检查 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
'where' 委托给 :all。
因此它去
rails/activerecord/lib/active_record/scoping/named.rb
def all
if current_scope
current_scope.clone
else
default_scoped
end
end
这部分我没看懂。为什么它适用于所有人?
委托可以设置为class方法吗?我虽然可以委托给class变量,实例变量。
在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)?
I don't understand this part. Why it goes to all
?
因为:
User.where(id: 1)
相当于:
User.all.where(id: 1)
此委托是为了简化 API,方法是在显式进行 none 时添加对 all
的隐式调用。
How does it get back to where
(relation/query_methods.rb)?
请记住,这是委派,而不是别名。所以,因为:
User.all
returns:
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 如果您有兴趣,可以深入了解 - 但我认为这超出了单个 Whosebug 答案的范围。
你能告诉我 Active Record 在我执行 User.where(id: 1)
时如何调用 'where' 吗?
我正在检查 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
'where' 委托给 :all。
因此它去
rails/activerecord/lib/active_record/scoping/named.rb
def all
if current_scope
current_scope.clone
else
default_scoped
end
end
这部分我没看懂。为什么它适用于所有人? 委托可以设置为class方法吗?我虽然可以委托给class变量,实例变量。
在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)?
I don't understand this part. Why it goes to
all
?
因为:
User.where(id: 1)
相当于:
User.all.where(id: 1)
此委托是为了简化 API,方法是在显式进行 none 时添加对 all
的隐式调用。
How does it get back to
where
(relation/query_methods.rb)?
请记住,这是委派,而不是别名。所以,因为:
User.all
returns:
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 如果您有兴趣,可以深入了解 - 但我认为这超出了单个 Whosebug 答案的范围。