我可以从 ActiveRecord::Concern 中调用 class 方法而不将其混合到另一个 class 中吗?

Can I invoke a class method from an ActiveRecord::Concern without mixing it into another class?

我正在创建一个 ActiveSupport::Concern that defines several class methods using the class_methods method. With a regular module it is possible to invoke the class methods directly using NameOfModule.target_method (e.g. in the stdlib class Math it's common to invoke acos 像这样 Math.acos(x)) 但我不知道如何执行类似的调用我的 Concern。这可能吗,如果可能的话,怎么做到的?

不,你不能,因为 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 将由包含您关注的 class 扩展。相关源代码如下:

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