ActiveSupport::Concern
is a Rails built-in module which adds some magic to the plain Ruby Module
. To take usage of it, a module should extend it:
module M extend ActiveSupport::Concern end
What kind of magic we talk about?
- It defines
class_methods
method which defines class methods from a given block:# A plain module module M def self.included(base) base.extend ClassMethods end module ClassMethods ... end end # A module with `ActiveSupport::Concern` module M extend ActiveSupport::Concern class_methods do ... end end
- Autoloads module’s dependency in a base class. If
Foo
module depends onBar
, withouthActiveSupport::Concern
both modules need to be included in a base class:module Foo def self.included(base) base.class_eval do def self.method_injected_by_foo ... end end end end module Bar def self.included(base) base.method_injected_by_foo end end class Host include Foo # We need to include this dependency for Bar include Bar # Bar is the module that Host really needs end
If both modules extend
ActiveSupport::Concern
, it’s enough to includeBar
only:module Foo extend ActiveSupport::Concern included do def self.method_injected_by_foo ... end end end module Bar extend ActiveSupport::Concern include Foo included do self.method_injected_by_foo end end class Host include Bar # It works, now Bar takes care of its dependencies end