Rails ActiveRecord 源码中频繁出现的的 spawn 是什么?

willx · 2023年02月21日 · 最后由 IChou 回复于 2023年02月22日 · 548 次阅读

今天下午闲来无事,研究了一下 ActiveReocrd 的代码,但是却发现了一件很令我困惑的事情。

我最开始对 ActiveReocrd 的实现心里大概有个猜测,但是看了源码之后却发现不是这样。

以 limit 方法为例:

# Specifies a limit for the number of records to retrieve.
#
#   User.limit(10) # generated SQL has 'LIMIT 10'
#
#   User.limit(10).limit(20) # generated SQL has 'LIMIT 20'
def limit(value)
  spawn.limit!(value)
end

def limit!(value) # :nodoc:
  self.limit_value = value
  self
end

可以看到这里有一个 limit 方法和一个 limit! 方法,我过去猜测的 ActiveRecord 的实现是 limit! 这种。

可通常我们在代码里使用的都是 limit 方法,limit! 在这里看起来像是一个被 deprecated 的旧方法。

翻了半天代码都没有看明白这个 spawn 到底是干什么的,大家有没有研究过这个的,或者有相关文章的,可以发发链接,一起学习~

1 楼 已删除

就是字面意思「派生」

它的实现应该是(看代码推测的,未确认)

https://github.com/rails/rails/blob/main/activerecord/lib/active_record/relation/spawn_methods.rb#L9

def spawn # :nodoc:
   already_in_scope?(klass.scope_registry) ? klass.all : clone
end

作用是避免后续操作影响原本 CollectionProxy 的上下文

至于 limit!, 它本就是一个 bang method,所以直接在原始的 CollectionProxy 对象上操作

#spawn 挂载到 CollectionProxy 上的代码在

https://github.com/rails/rails/blob/main/activerecord/lib/active_record/associations/collection_proxy.rb#L1108

需要 登录 后方可回复, 如果你还没有账号请 注册新账号