Module#included
позволяет модулям внедрять методы класса и экземпляра и выполнять связанный код из одного включения.
Документация для ActiveSupport :: Concern иллюстрирует типичное использование. Он внедряет методы класса в вызывающий класс и выполняет код. В этом случае добавление scope .
module M
def self.included(base)
base.extend ClassMethods
base.class_eval do
scope :disabled, -> { where(disabled: true) }
end
end
module ClassMethods
...
end
end
А вот версия ActiveSupport :: Concern, которая делает то же самое, но добавляет декларативный синтаксис sugar.
require 'active_support/concern'
module M
extend ActiveSupport::Concern
included do
scope :disabled, -> { where(disabled: true) }
end
class_methods do
...
end
end
С included
класс просто включает модуль. Это позволяет модулю быть единым пакетом: методы экземпляра, методы класса и код установки.
class Thing
# Class and instance methods are injected, and the new scope is added.
include M
end
Без included
модуль может внедрять только методы экземпляра. Методы класса должны быть добавлены отдельно, а также выполнять любой код установки.
module M
def some_instance_method
...
end
module ClassMethods
def setup
scope :disabled, -> { where(disabled: true) }
end
end
end
class Thing
# Inject the instance methods
include M
# Inject the class methods
extend M::ClassMethods
# Run any setup code.
setup
end
Другими примерами может быть регистрация класса, например, в качестве доступного плагина.
class Plugin
def self.included(base)
base.extend ClassMethods
bass.class_eval do
register_as_plugin(base)
end
end
module ClassMethods
def register_as_plugin(klass)
...
end
end
end
class Thing
include Plugin
end
Или добавление необходимых аксессоров.
class HasLogger
def self.included(base)
bass.class_eval do
attr_writer :logger
end
end
def logger
@logger ||= Rails.logger
end
end
class Thing
include HasLogger
end