Ruby模块 - 包括do end block

时间:2015-01-18 12:40:57

标签: ruby

有一个模块MyModule

module MyModule

  extend ActiveSupport::Concern

  def first_method
  end

  def second_method
  end

  included do
    second_class_method
  end

  module ClassMethods
    def first_class_method
    end

    def second_class_method
    end
  end
end

当某个类include成为此模块时,它将有2个方法作为实例方法公开(first_methodsecond_method)和2个类方法(first_class_method和{{ 1}}) - 很清楚。

据说,

  

second_class_method块将在类的上下文中执行   包括模块。

这究竟是什么意思?这意味着什么时候执行这个方法(included)呢?

2 个答案:

答案 0 :(得分:61)

这是一个实际的例子。

class MyClass
  include MyModule
end

当您将模块包含在类中时,将调用included挂钩。因此,second_class_method将在Class范围内调用。

这里发生的是

  1. first_methodsecond_method作为MyClass.

    的实例方法包含在内
    instance = MyClass.new
    instance.first_method
    # => whatever returned value of first_method is
    
  2. ClassMethods的方法会自动混合为MyClass的类方法。这是一种常见的Ruby模式,ActiveSupport::Concern封装。非Rails Ruby代码是

    module MyModule
      def self.included(base)
        base.extend ClassMethods
      end
    
      module ClassMethods
        def this_is_a_class_method
        end
      end
    end
    

    结果是

    MyClass.this_is_a_class_method
    

    或在你的情况下

    MyClass.first_class_method
    
  3. included是一个对以下代码有效的钩子

    # non-Rails version
    module MyModule
      def self.included(base)
        base.class_eval do
          # somecode
        end
      end
    end
    
    # Rails version with ActiveSupport::Concerns
    module MyModule
      included do
        # somecode
      end
    end
    

    对于常见模式,它主要是“语法糖”。在实践中发生的是,当您混合模块时,该代码在混合器类的上下文中执行。

答案 1 :(得分:16)

included包含到类中时,会调用

module,它用于定义关系,范围,验证,... 在你甚至从该类创建对象之前调用它。

例如

module M
...
  included do
    validates :attr, presence: true
    has_many :groups
  end
 ...
end