Ruby 模块 - 包括 do end 块

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28009772/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 06:40:33  来源:igfitidea点击:

Ruby modules - included do end block

ruby

提问by Andrey Deineko

There is a module MyModule:

有一个模块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

When some class includes this module, it will have 2 methods exposed as instance methods (first_methodand second_method) and 2 class methods (first_class_methodand second_class_method) - it is clear.

当某个类使用include此模块时,它将有 2 个方法公开为实例方法 ( first_methodand second_method) 和 2 个类方法 ( first_class_methodand second_class_method) - 很明显。

It is said, that

据说,那

includedblock will be executed within the context of the class that is including the module.

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

What does it mean exactly? Meaning, when exactly would this method (second_class_method) be executed?

它到底是什么意思?意思是,这个方法 ( second_class_method)到底什么时候执行?

回答by Simone Carletti

Here's a practical example.

这是一个实际的例子。

class MyClass
  include MyModule
end

When you will include the module in a class, the includedhook will be called. Therefore, second_class_methodwill be called within the scope of Class.

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

What happens here is

这里发生的是

  1. first_methodand second_methodare included as instance-methods of MyClass.

    instance = MyClass.new
    instance.first_method
    # => whatever returned value of first_method is
    
  2. The methods of ClassMethodsare automatically mixed as class methods of MyClass. This is a common Ruby pattern, that ActiveSupport::Concernencapsulates. The non-Rails Ruby code is

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

    Which results in

    MyClass.this_is_a_class_method
    

    or in your case

    MyClass.first_class_method
    
  3. includedis a hook that is effectively to the following code

    # 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
    

    It's mostly "syntactic sugar" for common patterns. What happens in practice, is that when you mix the module, that code is executed in the context of the mixer 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
    

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

回答by Nermin

includedis called when you include moduleinto a class, it is used for defining relations, scopes, validations, ... It gets called before you even have created object from that class.

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

example

例子

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