Ruby,如何在同一方法中获取方法的整个命名空间定义路径?

Ruby, How I can obtain the whole namespace definition path for a method inside the same method?

如何在同一方法中获取方法的整个命名空间定义路径?

使用这个例子来简化问题:

module Parent
    module Child
        def self.get_complete_namespace
            this_path = ???
            puts this_path.to_s
        end
    end
end

Parent::Child.get_complete_namespace
#=> "Parent::Child.get_complete_namespace"

所以要放置或打印出这个字符串“Parent::Child.get_complete_namespace”,使用 self super o 之类的东西的“this_path”变量值是多少?

我不知道有任何现成的功能,但您可以使用 __callee__(或 __method__

轻松创建一个
module Parent
  module Child
    def self.get_complete_namespace
      m = method(__callee__)
      "#{m.receiver.name}.#{m.name}"
    end
  end
end

Parent::Child.get_complete_namespace
#=> "Parent::Child.get_complete_namespace"

一些使用说明:

  • __callee____method__通常会return相同的符号。如果该方法是别名,则 __callee__ return 是被调用的方法名称,而 __method__ 将 return 定义的方法名称。
  • 对于class/module方法,您需要使用m.receiver。对于实例方法,您需要使用 m.owner。参见 Method

Class 示例:

module Parent
  class Child
    def self.get_complete_namespace
      m = method(__callee__)
      "#{m.receiver.name}.#{m.name}"
    end

    def get_complete_namespace
      m = method(__callee__)
      "#{m.owner.name}.#{m.name}"
    end

    alias_method :complete, :get_complete_namespace
  end
end

Parent::Child.get_complete_namespace
#=> "Parent::Child.get_complete_namespace"

Parent::Child.new.get_complete_namespace
#=> "Parent::Child.get_complete_namespace"

Parent::Child.new.complete
#=> "Parent::Child.complete"

编辑 - one-liner 版本:

def self.get_complete_namespace
  method(__callee__).instance_eval { "#{receiver.name}.#{name}" }
end

可以这样写get_complete_namespace

module Grandparent
  module Parent
    module Child
      def self.get_complete_namespace
        "#{Module.nesting.first}::#{__method__}"
      end
    end
  end 
end
Grandparent::Parent::Child.get_complete_namespace
  #=> "Grandparent::Parent::Child.get_complete_namespace"

Module::nesting and Kernel#method

方法Grandparent::Parent::Child::get_complete_namespace的操作线是否

Module.nesting

该方法会返回

[Grandparent::Parent::Child, Grandparent::Parent, Grandparent]