为什么 Rails 5 使用 ApplicationRecord 而不是 ActiveRecord::Base?

Why Rails 5 uses ApplicationRecord instead of ActiveRecord::Base?

我们知道Rails 5 添加了ApplicationRecord作为抽象class,它被我们的模型(ActiveRecord)继承。

但基本上,我认为我们用 ApplicationRecord 做的每个技术需求,我们也可以用 ActiveRecord::Base 做。例如:

module MyFeatures
  def do_something
    puts "Doing something"
  end
end

class ApplicationRecord < ActiveRecord::Base
  include MyFeatures
  self.abstract_class = true
end

所以现在每个模型都会附加MyFeatures的行为。但是我们也可以在 Rails 4:

中实现
ActiveRecord::Base.include(MyFeatures)

那么用[=14=有什么好处呢,你觉得有必要加ApplicationRecord吗?

虽然在基本的 Rails 应用程序中看起来是一样的,但一旦您开始使用 rails 引擎、插件/gem 或来自 ActiveRecord::Base 的直接方法,实际上就会有一个重要的区别.

  • ActiveRecord::Base.include(MyFeatures) 将特征直接混合到 ActiveRecord::Base 中,它永远存在于 ActiveRecord::Base 的所有后续使用中(它不能是 "unmixed") 并且在包含之后的任何代码中都无法再获得原始 ActiveRecord::Base 。如果一些混入的特性改变了默认的 ActiveRecord 行为,或者例如,这很容易导致问题。两个引擎/gems 试图包含同名方法。

  • 另一方面,ApplicationRecord 方法使特征 仅适用于从它继承的 类(模型),其他 类,以及直接使用 ActiveRecord::Base 保持原始状态,不受模块功能的影响。

这在使用引擎或 rails 插件时尤为重要,因为它允许它们将自己的模型逻辑与主应用程序的模型逻辑分开,这在 ApplicationRecord.[=19 之前是不可能的=]

所有这些在 this blog post and this github comment 中也有很好的描述。

这是为了扩展@BoraMa 的回答,并希望能消除围绕 ActiveRecord::Base.abstract_class 的一些困惑。

ActiveRecord::Base.abstract_class 至少可以追溯到 2012 年 1 月 20 日发布的 Rails 3.2.0 (http://api.rubyonrails.org/v3.2.0/classes/ActiveRecord/Inheritance/ClassMethods.html)。

Rails 4.0.0 改进了文档:http://api.rubyonrails.org/v4.0.0/classes/ActiveRecord/Inheritance/ClassMethods.html

所以,对于所有认为 ApplicationRecord 是全新事物的人来说,事实并非如此。这是一个改进,而不是一个破坏性的变化。没有向 ActiveRecord::Base 添加任何内容来使这项工作正常进行。

我在 Rails 4.2.6 项目上做了同样的事情,因为模型使用 UUID 作为 id 而不是整数,这需要更改默认值 ORDER BY。因此,我没有使用复制粘贴或关注点,而是使用 UuidModel class 和 self.abstract_class = true.

继承