ActiveSupport::Concern 模块是 Ruby 中很常用,且很重要的一个模块。它鼓励抽取可重用逻辑放到不同的concern里面,规范了 module mix 的代码风格,并且解决了模块加载之间的依赖问题。
鼓励公用逻辑抽取,规范代码风格
例如我们有 Post 和 Advertiser 两个类,这两个类拥有相同的判断是否是活跃状态的代码逻辑,scop、实例方法、类方法:
scope :active, -> {where(is_active: true)}
def active?
is_active
end
def self.all_active(reload = false)
@all_active = nil if reload
@all_active ||= active.all
end
为了重用这部分代码,我们将其抽取出来,放到一个module 中,如下:
module ActAsActivable
def self.included(base)
base.send(:include, InstanceMethods)
base.extend ClassMethods
base.class_eval do
scope :active, where(is_active: true)
end
end
module InstanceMethods
def active?
is_active
end
end
module ClassMethods
def all_active(reload = false)
@all_active = nil if reload
@all_active ||= active.all
end
end
end
在 ActAsActivable
model 中,为了使该module被 include 时可以为类添加这几个方法,我们将scope 实例方法和类方法写入module中,并分别用 InstanceMethods
和ClassMethods
包裹,并利用 hook 方法在被 include 的时候为新类添加新方法。
注意:
- 对于实例方法,我们完全可以不用InstanceMethods
模块来包裹,当它们被 include 的或者 extend 的时候,它们会自动成为新类的实例方法或类方法。
- 而类方法无论如何定义,都无法自动成为新类的类方法,看下面几个例子:
module A def self.test_a end