Module: ActiveSupport::Concern
- Included in:
- Callbacks, Configurable, Rescuable, Testing::Performance, Testing::SetupAndTeardown
- Defined in:
- lib/active_support/concern.rb
Overview
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
Class Method Summary collapse
Instance Method Summary collapse
Class Method Details
.extended(base) ⇒ Object
101 102 103 |
# File 'lib/active_support/concern.rb', line 101 def self.extended(base) base.instance_variable_set("@_dependencies", []) end |
Instance Method Details
#append_features(base) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/active_support/concern.rb', line 105 def append_features(base) if base.instance_variable_defined?("@_dependencies") base.instance_variable_get("@_dependencies") << self return false else return false if base < self @_dependencies.each { |dep| base.send(:include, dep) } super base.extend const_get("ClassMethods") if const_defined?("ClassMethods") if const_defined?("InstanceMethods") base.send :include, const_get("InstanceMethods") ActiveSupport::Deprecation.warn "The InstanceMethods module inside ActiveSupport::Concern will be " \ "no longer included automatically. Please define instance methods directly in #{self} instead.", caller end base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block") end end |
#included(base = nil, &block) ⇒ Object
123 124 125 126 127 128 129 |
# File 'lib/active_support/concern.rb', line 123 def included(base = nil, &block) if base.nil? @_included_block = block else super end end |