首页 > 解决方案 > 什么是 Ruby module.included?

问题描述

我试图更好地理解 Ruby 中的元编程,但对什么Module.included是元编程感到困惑?我目前的理解是,当模块被包含到另一个模块或类中时,这是 Ruby 调用的回调。除此之外,这些用于哪些类型的(元)编程结构?有什么例子吗?

标签: ruby-on-railsrubymetaprogramming

解决方案


Module#included允许模块从单个包含注入类和实例方法,并执行相关代码。

ActiveSupport::Concern的文档说明了一个典型的用法。它将类方法注入调用类,并执行代码。在这种情况下,添加一个范围

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

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

推荐阅读