A typical module looks like this:

  module M
    def self.included(base)
      base.extend ClassMethods
      scope :disabled, where(:disabled => true)
    end

    module ClassMethods
      ...
    end
  end

By using ActiveSupport::Concern the above module could instead be written as:

  require 'active_support/concern'

  module M
    extend ActiveSupport::Concern

    included do
      scope :disabled, where(:disabled => true)
    end

    module ClassMethods
      ...
    end
  end

Moreover, it gracefully handles module dependencies. Given a Foo module and a Bar module which depends on the former, we would typically write the following:

  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

But why should Host care about Bar’s dependencies, namely Foo? We could try to hide these from Host directly including Foo in Bar:

  module Bar
    include Foo
    def self.included(base)
      base.method_injected_by_foo
    end
  end

  class Host
    include Bar
  end

Unfortunately this won’t work, since when Foo is included, its base is the Bar module, not the Host class. With ActiveSupport::Concern, module dependencies are properly resolved:

  require 'active_support/concern'

  module Foo
    extend ActiveSupport::Concern
    included do
      class_eval do
        def self.method_injected_by_foo
          ...
        end
      end
    end
  end

  module Bar
    extend ActiveSupport::Concern
    include Foo

    included do
      self.method_injected_by_foo
    end
  end

  class Host
    include Bar # works, Bar takes care now of its dependencies
  end
Methods
A
E
I
Class Public methods
extended(base)
     # File activesupport/lib/active_support/concern.rb, line 101
101:     def self.extended(base)
102:       base.instance_variable_set("@_dependencies", [])
103:     end
Instance Public methods
append_features(base)
     # File activesupport/lib/active_support/concern.rb, line 105
105:     def append_features(base)
106:       if base.instance_variable_defined?("@_dependencies")
107:         base.instance_variable_get("@_dependencies") << self
108:         return false
109:       else
110:         return false if base < self
111:         @_dependencies.each { |dep| base.send(:include, dep) }
112:         super
113:         base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
114:         if const_defined?("InstanceMethods")
115:           base.send :include, const_get("InstanceMethods")
116:           ActiveSupport::Deprecation.warn "The InstanceMethods module inside ActiveSupport::Concern will be " \
117:             "no longer included automatically. Please define instance methods directly in #{self} instead.", caller
118:         end
119:         base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block")
120:       end
121:     end
included(base = nil, &block)
     # File activesupport/lib/active_support/concern.rb, line 123
123:     def included(base = nil, &block)
124:       if base.nil?
125:         @_included_block = block
126:       else
127:         super
128:       end
129:     end