Ruby模块 - 包括do end block

And*_*eko 32 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
Run Code Online (Sandbox Code Playgroud)

当某个类include是这个模块时,它将有2个方法暴露为实例方法(first_methodsecond_method)和2个类方法(first_class_methodsecond_class_method) - 很明显.

有人说,那

included 块将在包含模块的类的上下文中执行.

这究竟是什么意思?意思是,什么时候second_class_method执行这个方法()?

Sim*_*tti 69

这是一个实际的例子.

class MyClass
  include MyModule
end
Run Code Online (Sandbox Code Playgroud)

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

这里发生的是

  1. first_methodsecond_method作为实例方法包含在内MyClass.

    instance = MyClass.new
    instance.first_method
    # => whatever returned value of first_method is
    
    Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)

    结果如何

    MyClass.this_is_a_class_method
    
    Run Code Online (Sandbox Code Playgroud)

    或者在你的情况下

    MyClass.first_class_method
    
    Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)

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

  • 一旦包含者包含您的模块,它将立即被提升.这实际上会导致ruby代码解析过程并导致解释器立即崩溃.你可以自己试试. (4认同)
  • 一切听起来都很合理,但仍然......让我们看一下例子.如果`second_class_method`实现为`raise'怎么办我什么时候被提出?"`什么时候会被提出? (2认同)

Ner*_*min 17

included当你包含module在一个类中时,它被用来定义关系,范围,验证,......它甚至在你从该类创建对象之前被调用.

module M
...
  included do
    validates :attr, presence: true
    has_many :groups
  end
 ...
end
Run Code Online (Sandbox Code Playgroud)

  • 它不会“在包含该模块的类的上下文中设置”。“validates”是一种方法。您在模块主体内运行的任何方法都会在“加载时”在该模块的上下文中运行。你会得到的是“NoMethodError”,因为对于一个模块来说,“validates”并没有多大意义 (3认同)