A brief refresher about Rails `ActiveSupport::Concern`

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?

  1. 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
  2. Autoloads module’s dependency in a base class. If Foo module depends on Bar, withouth ActiveSupport::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 include Bar 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

     

 

Igor Springer

I build web apps. From time to time I put my thoughts on paper. I hope that some of them will be valuable for you. To teach is to learn twice.

 

Leave a Reply

Your email address will not be published. Required fields are marked *