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

Time:04-21

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

Using this example to make easy the question:

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"

So to puts or print out this string "Parent::Child.get_complete_namespace", what is the "this_path" variable value using self super o something like that?

CodePudding user response:

I don't know of any existing functions for this, though you could pretty easily create one using __callee__ (or __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"

Some usages notes:

  • __callee__ and __method__ will usually return the same symbol. If the method is aliased, then __callee__ returns the method name that was invoked, while __method__ will return the method name as it was defined.
  • For a class/module method, you need to use m.receiver. For an instance method, you need to use m.owner. See Method.

Class example:

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"

CodePudding user response:

You can write get_complete_namespace as follows.

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"

See Module::nesting and Kernel#method.

Had the operative line of the method Grandparent::Parent::Child::get_complete_namespace been

Module.nesting

the method would have returned

[Grandparent::Parent::Child, Grandparent::Parent, Grandparent]
  • Related