什么是 Ruby module.included?
What is Ruby module.included?
我试图更好地理解 Ruby 中的元编程,但对 Module.included
是什么感到困惑?我目前的理解是,这是一个由 Ruby 调用的回调,每当模块被包含到另一个模块或 class 中时。除此之外,这些使用了哪些类型的(元)编程结构?有例子吗?
Module#included
允许模块从单个包含中注入 class 和实例方法,并执行相关代码。
documentation for ActiveSupport::Concern illustrates a typical use. It's injecting class methods into the calling class, and executing code. In this case, adding a 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 版本,但添加了声明性语法糖。
require 'active_support/concern'
module M
extend ActiveSupport::Concern
included do
scope :disabled, -> { where(disabled: true) }
end
class_methods do
...
end
end
With included
a class 只包含模块。它允许模块成为一个简洁的包:实例方法、class 方法和设置代码。
class Thing
# Class and instance methods are injected, and the new scope is added.
include M
end
没有included
,模块只能注入实例方法。 Class 方法必须单独添加,以及执行任何设置代码。
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,例如作为可用插件。
module Plugin
def self.included(base)
base.extend ClassMethods
base.class_eval do
register_as_plugin(base)
end
end
module ClassMethods
def register_as_plugin(klass)
...
end
end
end
class Thing
include Plugin
end
或添加必要的访问器。
module HasLogger
def self.included(base)
base.class_eval do
attr_writer :logger
end
end
def logger
@logger ||= Rails.logger
end
end
class Thing
include HasLogger
end
我试图更好地理解 Ruby 中的元编程,但对 Module.included
是什么感到困惑?我目前的理解是,这是一个由 Ruby 调用的回调,每当模块被包含到另一个模块或 class 中时。除此之外,这些使用了哪些类型的(元)编程结构?有例子吗?
Module#included
允许模块从单个包含中注入 class 和实例方法,并执行相关代码。
documentation for ActiveSupport::Concern illustrates a typical use. It's injecting class methods into the calling class, and executing code. In this case, adding a 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 版本,但添加了声明性语法糖。
require 'active_support/concern'
module M
extend ActiveSupport::Concern
included do
scope :disabled, -> { where(disabled: true) }
end
class_methods do
...
end
end
With included
a class 只包含模块。它允许模块成为一个简洁的包:实例方法、class 方法和设置代码。
class Thing
# Class and instance methods are injected, and the new scope is added.
include M
end
没有included
,模块只能注入实例方法。 Class 方法必须单独添加,以及执行任何设置代码。
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,例如作为可用插件。
module Plugin
def self.included(base)
base.extend ClassMethods
base.class_eval do
register_as_plugin(base)
end
end
module ClassMethods
def register_as_plugin(klass)
...
end
end
end
class Thing
include Plugin
end
或添加必要的访问器。
module HasLogger
def self.included(base)
base.class_eval do
attr_writer :logger
end
end
def logger
@logger ||= Rails.logger
end
end
class Thing
include HasLogger
end