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

Posted

技术标签:

【中文标题】为啥 Rails 5 使用 ApplicationRecord 而不是 ActiveRecord::Base?【英文标题】:Why Rails 5 uses ApplicationRecord instead of ActiveRecord::Base?为什么 Rails 5 使用 ApplicationRecord 而不是 ActiveRecord::Base? 【发布时间】:2016-09-18 11:26:36 【问题描述】:

我们知道 Rails 5 添加了ApplicationRecord 作为我们的模型继承的抽象类 (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)

那么使用ApplicationRecord有什么好处,你觉得有必要加ApplicationRecord吗?

【问题讨论】:

【参考方案1】:

虽然在基本的 Rails 应用程序中可能看起来相同,但当您开始使用来自 ActiveRecord::Base 的 Rails 引擎、插件/gem 或直接方法时,实际上会有一个重要的区别。

ActiveRecord::Base.include(MyFeatures) 将特征直接混合到ActiveRecord::Base 中,并且它永远存在于ActiveRecord::Base 的所有以后使用中(它不能“未混合”)并且没有办法获得原始@ 987654327@ 不再包含在任何代码中。如果某些混合功能更改了默认的 ActiveRecord 行为,或者例如两个引擎/gem 试图包含同名方法。

另一方面,ApplicationRecord 方法使特性仅适用于继承自它的类(模型)、其他类,以及直接使用 @987654329 @保持原始状态,不受模块功能的影响。

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

this blog post 和 this github comment 也很好地描述了所有这些。

【讨论】:

每个扩展 ActiveRecord::Base 的 gem 现在会因此被破坏吗?如果是这样,那将产生大量的维护和技术债务。 感谢 BoraMa 提供如此详细的回答并提及博客链接。请务必访问博客链接,因为它通过示例非常清楚地解释了。作为 Rails 的新手,它提供了非常丰富的信息。【参考方案2】:

这是对@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 类和self.abstract_class = true 进行继承。

【讨论】:

我记得 Rails 2.x 中的 abstract_class

以上是关于为啥 Rails 5 使用 ApplicationRecord 而不是 ActiveRecord::Base?的主要内容,如果未能解决你的问题,请参考以下文章

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

stylesheet_pack_tag 在带有 webpacker gem 的 rails 5.1 中找不到 app/javascript/src/application.css

将Chartkick与rails 5.2 api应用集成?

为啥撇号会使 Rails 5.1.5 请求解析崩溃?

Rails 5:为啥即使我删除了迁移文件,rails 也会向 schema.rb 添加列

JQuery 匹配高度在 Rails 5.2 上不起作用