123456789_123456789_123456789_123456789_123456789_

Module: ActiveSupport::Concern

Relationships & Source Files
Namespace Children
Exceptions:
Extension / Inclusion / Inheritance Descendants
Extended In:
::AbstractController::AssetPaths, ::AbstractController::Caching, ::AbstractController::Caching::Fragments, ::AbstractController::Callbacks, ::AbstractController::Helpers, ::AbstractController::Logger, ::AbstractController::Rendering, ::AbstractController::UrlFor, ::ActionCable::Channel::Broadcasting, ::ActionCable::Channel::Callbacks, ::ActionCable::Channel::Naming, ::ActionCable::Channel::PeriodicTimers, ::ActionCable::Channel::Streams, ::ActionCable::Channel::TestCase::Behavior, ::ActionCable::Connection::Callbacks, ::ActionCable::Connection::Identification, ::ActionCable::Connection::InternalChannel, ::ActionCable::Connection::TestCase::Behavior, ::ActionCable::Server::Worker::ActiveRecordConnectionManagement, ::ActionController::AllowBrowser, ::ActionController::ApiRendering, ::ActionController::Caching, ::ActionController::ConditionalGet, ::ActionController::ContentSecurityPolicy, ::ActionController::Cookies, ::ActionController::DataStreaming, ::ActionController::DefaultHeaders, ::ActionController::EtagWithFlash, ::ActionController::EtagWithTemplateDigest, ::ActionController::Flash, ::ActionController::FormBuilder, ::ActionController::Helpers, ::ActionController::HttpAuthentication::Basic::ControllerMethods, ::ActionController::Instrumentation, ::ActionController::Live, ::ActionController::Logging, ::ActionController::ParameterEncoding, ::ActionController::ParamsWrapper, ::ActionController::PermissionsPolicy, ::ActionController::RateLimiting, ::ActionController::Redirecting, ::ActionController::Renderers, ::ActionController::Renderers::All, ::ActionController::Rendering, ::ActionController::RequestForgeryProtection, ::ActionController::Rescue, ::ActionController::TestCase::Behavior, ::ActionController::UrlFor, ::ActionDispatch::Assertions, ::ActionDispatch::Assertions::RoutingAssertions, ::ActionDispatch::Assertions::RoutingAssertions::WithIntegrationRouting, ::ActionDispatch::Http::MimeNegotiation, ::ActionDispatch::Http::Parameters, ::ActionDispatch::IntegrationTest::Behavior, ::ActionDispatch::IntegrationTest::UrlOptions, ::ActionDispatch::Routing::RouteSet::MountedHelpers, ::ActionDispatch::Routing::UrlFor, ::ActionMailbox::Callbacks, ::ActionMailbox::Routing, ::ActionMailer::Callbacks, ::ActionMailer::DeliveryMethods, ::ActionMailer::FormBuilder, ::ActionMailer::Parameterized, ::ActionMailer::Previews, ::ActionMailer::QueuedDelivery, ::ActionMailer::Rescuable, ::ActionMailer::TestCase::Behavior, ::ActionMailer::TestCase::ClearTestDeliveries, ::ActionText::Attachable, ::ActionText::Attachments::Conversion, ::ActionText::Attachments::Minification, ::ActionText::Attachments::TrixConversion, ::ActionText::Attribute, ::ActionText::Rendering, ::ActionText::Serialization, ::ActionView::CollectionCaching, ::ActionView::Helpers, ::ActionView::Helpers::FormHelper, ::ActionView::Helpers::FormTagHelper, ::ActionView::Helpers::SanitizeHelper, ::ActionView::Helpers::TextHelper, ::ActionView::Helpers::TranslationHelper, ::ActionView::Helpers::UrlHelper, ::ActionView::Layouts, ::ActionView::Rendering, ::ActionView::TestCase::Behavior, ::ActionView::ViewPaths, ::ActiveJob::Callbacks, ::ActiveJob::Continuable, ::ActiveJob::Core, ::ActiveJob::Enqueuing, ::ActiveJob::Exceptions, ::ActiveJob::Execution, ::ActiveJob::Instrumentation, ::ActiveJob::Logging, ::ActiveJob::QueueAdapter, ::ActiveJob::QueueName, ::ActiveJob::QueuePriority, ::ActiveJob::TestHelper::TestQueueAdapter, ::ActiveModel::API, ::ActiveModel::AttributeMethods, ::ActiveModel::AttributeRegistration, ::ActiveModel::Attributes, ::ActiveModel::Attributes::Normalization, ::ActiveModel::Conversion, ::ActiveModel::Dirty, ::ActiveModel::Model, ::ActiveModel::SchematizedJson, ::ActiveModel::SecurePassword, ::ActiveModel::Serializers::JSON, ::ActiveModel::Type::SerializeCastValue, ::ActiveModel::Validations, ::ActiveModel::Validations::Callbacks, ::ActiveRecord::Associations, ::ActiveRecord::AttributeMethods, ::ActiveRecord::AttributeMethods::BeforeTypeCast, ::ActiveRecord::AttributeMethods::Dirty, ::ActiveRecord::AttributeMethods::PrimaryKey, ::ActiveRecord::AttributeMethods::Query, ::ActiveRecord::AttributeMethods::Read, ::ActiveRecord::AttributeMethods::Serialization, ::ActiveRecord::AttributeMethods::TimeZoneConversion, ::ActiveRecord::AttributeMethods::Write, ::ActiveRecord::Attributes, ::ActiveRecord::AutosaveAssociation, ::ActiveRecord::Callbacks, ::ActiveRecord::ConnectionAdapters::ColumnMethods, ::ActiveRecord::ConnectionAdapters::Deduplicable, ::ActiveRecord::ConnectionAdapters::MySQL::ColumnMethods, ::ActiveRecord::ConnectionAdapters::MySQL::Quoting, ::ActiveRecord::ConnectionAdapters::PostgreSQL::ColumnMethods, ::ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting, ::ActiveRecord::ConnectionAdapters::Quoting, ::ActiveRecord::ConnectionAdapters::SQLite3::Quoting, ::ActiveRecord::Core, ::ActiveRecord::CounterCache, ::ActiveRecord::Delegation, ::ActiveRecord::Delegation::ClassSpecificRelation, ::ActiveRecord::Encryption::Configurable, ::ActiveRecord::Encryption::Contexts, ::ActiveRecord::Encryption::EncryptableRecord, ::ActiveRecord::Encryption::ExtendedDeterministicQueries::CoreQueries, ::ActiveRecord::Generators::Migration, ::ActiveRecord::Inheritance, ::ActiveRecord::Integration, ::ActiveRecord::Locking::Optimistic, ::ActiveRecord::ModelSchema, ::ActiveRecord::NestedAttributes, ::ActiveRecord::NoTouching, ::ActiveRecord::Persistence, ::ActiveRecord::Railties::ControllerRuntime, ::ActiveRecord::ReadonlyAttributes, ::ActiveRecord::Reflection, ::ActiveRecord::Sanitization, ::ActiveRecord::Schema::Definition, ::ActiveRecord::Scoping, ::ActiveRecord::Scoping::Default, ::ActiveRecord::Scoping::Named, ::ActiveRecord::SecurePassword, ::ActiveRecord::SecureToken, ::ActiveRecord::Serialization, ::ActiveRecord::SignedId, ::ActiveRecord::Store, ::ActiveRecord::Suppressor, ::ActiveRecord::TestFixtures, ::ActiveRecord::Timestamp, ::ActiveRecord::TokenFor, ::ActiveRecord::Transactions, ::ActiveRecord::Validations, ::ActiveStorage::Attached::Model, ::ActiveStorage::Reflection::ActiveRecordExtensions, ActionableError, Callbacks, ColorizeLogging, Configurable, LoggerSilence, LoggerThreadSafeLevel, Rescuable, Testing::ConstantLookup, Testing::FileFixtures, ::Rails::Command::Behavior, ::Rails::Command::EnvironmentArgument, ::Rails::Generators::Migration, ::Rails::Generators::Testing::Behavior, ::Rails::Railtie::Configurable
Defined in: activesupport/lib/active_support/concern.rb

Overview

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 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 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.

Class Method Summary

Instance Method Summary

Class Method Details

.extended(base)

This method is for internal use only.
[ GitHub ]

  
# File 'activesupport/lib/active_support/concern.rb', line 125

def self.extended(base) # :nodoc:
  base.instance_variable_set(:@_dependencies, [])
end

Instance Method Details

#append_features(base)

This method is for internal use only.
[ GitHub ]

  
# File 'activesupport/lib/active_support/concern.rb', line 129

def append_features(base) # :nodoc:
  if base.instance_variable_defined?(:@_dependencies)
    base.instance_variable_get(:@_dependencies) << self
    false
  else
    return false if base < self
    @_dependencies.each { |dep| base.include(dep) }
    super
    base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
    base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block)
  end
end

#class_methods(&class_methods_module_definition)

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)
[ 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)

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.

[ 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

#prepend_features(base)

This method is for internal use only.
[ GitHub ]

  
# File 'activesupport/lib/active_support/concern.rb', line 142

def prepend_features(base) # :nodoc:
  if base.instance_variable_defined?(:@_dependencies)
    base.instance_variable_get(:@_dependencies).unshift self
    false
  else
    return false if base < self
    @_dependencies.each { |dep| base.prepend(dep) }
    super
    base.singleton_class.prepend const_get(:ClassMethods) if const_defined?(:ClassMethods)
    base.class_eval(&@_prepended_block) if instance_variable_defined?(:@_prepended_block)
  end
end

#prepended(base = nil, &block)

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.

[ 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