ActiveRecord::Relation是如何添加到Rails的模型中的?为什么每个模型都有单独的Relation类?

3
假设我有一个Rails模型:class Project < ActiveRecord::Base 在Rails控制台中:
> Project.all
=> #<ActiveRecord::Relation []>

那看起来很合理。不过,最初的回答是:
> Project.all.class
=> Project::ActiveRecord_Relation

"Project::ActiveRecord_Relation"是什么?具体而言:
  • 它是如何被“添加”(命名空间)到我的模型类中的?
  • 它如何正确响应is_a?Project.all.is_a?(ActiveRecord::Relation)返回true(预期结果),但是Project::ActiveRecord_Relation实际上是ActiveRecord::Relation的一个实例,还是其他东西?
  • 为什么要这样做?为什么不直接返回ActiveRecord::Relation,而是返回Project::ActiveRecord_Relation
(这是在Rails 5.1的情况下,如果在旧版本或新版本中更改了内容,请注意。)
(如果有人能想出更好的标题,我可以接受标题编辑。)
2个回答

3

检查ActiveRecord中的这行代码。

https://github.com/rails/rails/blob/f40860800c231ecd1daef6cf6b5a8a8eda76478d/activerecord/lib/active_record/relation/delegation.rb#L23

mangled_name = klass.name.gsub("::", "_")

所以,针对你的问题:


1
所有来自Project的类方法都会混入Project::ActiveRecord_Relation中,这就是为什么你可以使用Project.where(...).some_scope这样的语法,并且也是为什么你可以将作用域实现为显式的类方法。 - undefined
谢谢!我没意识到类方法可以作为作用域使用;看来这是我在这里错过的关键洞察。我给这个答案点了赞,但我会给@chumakoff一个✅,因为他更好地回答了“为什么”。 - undefined

2
您所提出的实际上有两个问题:
1.它是如何工作的? 2.为什么会这样?(为了什么?)
@arieljuod已经给出了一些解释和链接。
然而第二个问题仍未得到回答。
还有一个类似的问题存在,我希望它能帮助您找到所有的答案: ActiveRecord :: Relation对象如何调用类方法 看起来这两个问题(通过链接和您的问题)可以互相解答。
请看一下nikita-shilnikov的答案。祝您调查顺利!

非常有帮助,谢谢!我之前没有意识到可以将类方法用作作用域,所以没有考虑过这个方向的探索。看起来支持这一点似乎是这种模式背后的主要动机。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接