Можно ли вызвать метод класса из ActiveRecord::Concern, не смешивая его с другим классом?

Я создаю ActiveSupport::Concern, который определяет несколько методов класса, используя class_methods метод. С обычным модулем можно вызывать методы класса напрямую, используя NameOfModule.target_method (например, в классе Math stdlib обычно вызывается acos, например, Math.acos(x)) но я затрудняюсь найти способ выполнить аналогичный вызов мой Concern, Возможно ли это, если да, то как?

1 ответ

Решение

Нет, вы не можете, потому что методы, определенные в блоке class_methods на самом деле определены в модуле Foo::ClassMethods (Foo ваша забота). Вот соответствующий исходный код ActiveSupport::Concern

module ActiveSupport
  # ...
  module Concern
    # ...
    def class_methods(&class_methods_module_definition)
      mod = const_defined?(:ClassMethods, false) ?
        const_get(:ClassMethods) :
        const_set(:ClassMethods, Module.new)

      mod.module_eval(&class_methods_module_definition)
    end
  end
end

Ты это видишь class_methods просто создает модуль ClassMethods для вас, если это не определено вами. Методы, которые вы определили, являются просто методами экземпляра в этом модуле, поэтому вы не можете вызывать его на уровне модуля.

Позже, модуль ClassMethods будет расширен за счет класса, который включает в себя вашу проблему. Вот соответствующий исходный код:

module ActiveSupport
  # ...
  module Concern
    def append_features(base)
      if base.instance_variable_defined?(:@_dependencies)
        # ...
      else
        # ...
        base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)  # <-- Notice this line
        # ...
      end
    end
  end
end
Другие вопросы по тегам