为什么 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
.
继承
我们知道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
.