Skip to Content Skip to Search
Ruby on Rails 8.0.2.1

Module ActiveSupport::Concern

v8.0.2.1

Active Support Concern

A typical module looks like this:

module M
 def self.included(base)
 base.extend ClassMethods
 base.class_eval do
 scope :disabled, -> { where(disabled: true) }
 end
 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
 class_methods do
 ...
 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
 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

Prepending concerns

Just like include, concerns also support prepend with a corresponding prepended do callback. module ClassMethods or class_methods do are prepended as well.

prepend is also used for any dependencies.

Methods
C
I
P

Instance Public methods

class_methods(&class_methods_module_definition) Link

Define class methods from given block. You can define private class methods as well.

module Example
 extend ActiveSupport::Concern
 class_methods do
 def foo; puts 'foo'; end
 private
 def bar; puts 'bar'; end
 end
end
class Buzz
 include Example
end
Buzz.foo # => "foo"
Buzz.bar # => private method 'bar' called for Buzz:Class(NoMethodError)

Source: | on GitHub

# File activesupport/lib/active_support/concern.rb, line 209
def class_methods(&class_methods_module_definition)
 mod = const_defined?(:ClassMethods, false) ?
 const_get(:ClassMethods) :
 const_set(:ClassMethods, Module.new)
 mod.module_eval(&class_methods_module_definition)
end

included(base = nil, &block) Link

Evaluate given block in context of base class, so that you can write class macros here. When you define more than one included block, it raises an exception.

Source: | on GitHub

# File activesupport/lib/active_support/concern.rb, line 158
def included(base = nil, &block)
 if base.nil?
 if instance_variable_defined?(:@_included_block)
 if @_included_block.source_location != block.source_location
 raise MultipleIncludedBlocks
 end
 else
 @_included_block = block
 end
 else
 super
 end
end

prepended(base = nil, &block) Link

Evaluate given block in context of base class, so that you can write class macros here. When you define more than one prepended block, it raises an exception.

Source: | on GitHub

# File activesupport/lib/active_support/concern.rb, line 175
def prepended(base = nil, &block)
 if base.nil?
 if instance_variable_defined?(:@_prepended_block)
 if @_prepended_block.source_location != block.source_location
 raise MultiplePrependBlocks
 end
 else
 @_prepended_block = block
 end
 else
 super
 end
end

AltStyle によって変換されたページ (->オリジナル) /