123456789_123456789_123456789_123456789_123456789_

Module: ActiveSupport::Concern

Relationships & Source Files
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::Connection::Identification, ::ActionCable::Connection::InternalChannel, ::ActionCable::Server::Worker::ActiveRecordConnectionManagement, ::ActionController::ApiRendering, ::ActionController::Caching, ::ActionController::ConditionalGet, ::ActionController::ContentSecurityPolicy, ActionController::Cookies, ::ActionController::DataStreaming, ::ActionController::EtagWithFlash, ::ActionController::EtagWithTemplateDigest, ::ActionController::Flash, ::ActionController::ForceSSL, ::ActionController::FormBuilder, ::ActionController::Helpers, ::ActionController::HttpAuthentication::Basic::ControllerMethods, ::ActionController::Instrumentation, ::ActionController::Live, ::ActionController::ParameterEncoding, ::ActionController::ParamsWrapper, ::ActionController::Redirecting, ::ActionController::Renderers, ::ActionController::Renderers::All, ::ActionController::Rendering, ::ActionController::RequestForgeryProtection, ::ActionController::Rescue, ::ActionController::Streaming, ::ActionController::StrongParameters, ::ActionController::TestCase::Behavior, ::ActionController::Testing, ::ActionController::UrlFor, ::ActionDispatch::Assertions, ::ActionDispatch::Http::MimeNegotiation, ::ActionDispatch::Http::Parameters, ::ActionDispatch::IntegrationTest::Behavior, ::ActionDispatch::IntegrationTest::UrlOptions, ::ActionDispatch::Routing::RouteSet::MountedHelpers, ::ActionDispatch::Routing::UrlFor, ActionDispatch::SystemTesting::TestHelpers::UndefMethods, ::ActionMailer::DeliveryMethods, ::ActionMailer::Parameterized, ::ActionMailer::Previews, ::ActionMailer::Rescuable, ::ActionMailer::TestCase::Behavior, ::ActionMailer::TestCase::ClearTestDeliveries, ActionView::CollectionCaching, ::ActionView::Helpers, ::ActionView::Helpers::AssetTagHelper, ::ActionView::Helpers::FormHelper, ::ActionView::Helpers::FormTagHelper, ::ActionView::Helpers::SanitizeHelper, ::ActionView::Helpers::TagHelper, ::ActionView::Helpers::TextHelper, ActionView::Helpers::TranslationHelper, ::ActionView::Helpers::UrlHelper, ::ActionView::Layouts, ::ActionView::Rendering, ::ActionView::TestCase::Behavior, ::ActionView::ViewPaths, ::ActiveJob::Callbacks, ::ActiveJob::Core, ::ActiveJob::Enqueuing, ::ActiveJob::Exceptions, ::ActiveJob::Execution, ActiveJob::Logging, ::ActiveJob::QueueAdapter, ::ActiveJob::QueueName, ::ActiveJob::QueuePriority, ::ActiveJob::TestHelper::TestQueueAdapter, ActiveJob::Translation, ::ActiveModel::AttributeMethods, ::ActiveModel::Attributes, ::ActiveModel::Conversion, ::ActiveModel::Dirty, ::ActiveModel::Model, ::ActiveModel::SecurePassword, ::ActiveModel::Serializers::JSON, ::ActiveModel::Validations, ::ActiveModel::Validations::Callbacks, ::ActiveRecord::Aggregations, ::ActiveRecord::Associations, ::ActiveRecord::AttributeAssignment, ActiveRecord::AttributeDecorators, ::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::Core, ::ActiveRecord::CounterCache, ::ActiveRecord::DefineCallbacks, ActiveRecord::Delegation, ActiveRecord::Delegation::ClassSpecificRelation, ::ActiveRecord::Generators::Migration, ::ActiveRecord::Inheritance, ::ActiveRecord::Integration, ::ActiveRecord::Locking::Optimistic, ::ActiveRecord::ModelSchema, ::ActiveRecord::NestedAttributes, ::ActiveRecord::NoTouching, ::ActiveRecord::Persistence, ::ActiveRecord::QueryMethods, ActiveRecord::Railties::ControllerRuntime, ::ActiveRecord::ReadonlyAttributes, ::ActiveRecord::Reflection, ::ActiveRecord::Sanitization, ::ActiveRecord::Scoping, ::ActiveRecord::Scoping::Default, ::ActiveRecord::Scoping::Named, ::ActiveRecord::SecureToken, ::ActiveRecord::Serialization, ::ActiveRecord::Store, ::ActiveRecord::Suppressor, ::ActiveRecord::TestFixtures, ::ActiveRecord::Timestamp, ::ActiveRecord::TouchLater, ::ActiveRecord::Transactions, ::ActiveRecord::Validations, Callbacks, Configurable, ActiveSupport::LoggerThreadSafeLevel, Rescuable, Testing::ConstantLookup, Testing::FileFixtures, ::LoggerSilence, Rails::Command::Behavior, Rails::Command::EnvironmentArgument, ::Rails::Generators::Migration, ::Rails::Generators::Testing::Behaviour, ::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

Instance Method Summary

Instance Method Details

#append_features(base)

[ GitHub ]

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

def append_features(base)
  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)

[ GitHub ]

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

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)

[ GitHub ]

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

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