Модули 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_method и second_method) и 2 метода класса (first_class_method и second_class_method) - это понятно.

Говорят, что

Блок

included будет выполняться в контексте класса, который включает модуль.

Что это значит? Смысл, когда именно этот метод (second_class_method) будет выполнен?

Ответы

Ответ 1

Вот практический пример.

class MyClass
  include MyModule
end

Когда вы включите модуль в класс, будет вызван крюк included. Поэтому second_class_method будет вызываться в рамках Class.

Что происходит здесь,

  • first_method и second_method включены в качестве примеров-методов MyClass.

    instance = MyClass.new
    instance.first_method
    # => whatever returned value of first_method is
    
  • Методы ClassMethods автоматически смешиваются как методы класса MyClass. Это обычный шаблон Ruby, который ActiveSupport::Concern инкапсулирует. Код Ruby без Rails

    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
    
  • 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
    

    В основном это "синтаксический сахар" для общих паттернов. Что происходит на практике, так это то, что при смешивании модуля этот код выполняется в контексте класса микшера.

Ответ 2

included вызывается, когда вы включаете module в класс, он используется для определения отношений, областей, валидаций,... Он вызывается до того, как вы даже создали объект из этого класса.

Пример

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