Saman Mohamadi
Saman Mohamadi

Reputation: 4662

How to access parent/sibling module methods

Is there any way to access baz_method inside class Qux without mentioning module namespace from first? When there are many nested modules the code doesn't look clean.

module Foo
  module Bar
    module Baz
      class Qux
        def self.qux_method
          Foo::Bar::Baz.baz_method  
        end
      end
      def self.baz_method
      end
    end 
  end
end

Upvotes: 8

Views: 4897

Answers (3)

Linuxios
Linuxios

Reputation: 35793

Note: Unless you're explicitly looking for relative module access, this metaprogramming is unnecessary. Use @drhining's solution instead.

You can dynamically climb the module hierarchy using Module#nesting:

module Foo
  module Bar
    module Baz
      class Qux
        def self.qux_method
          Module.nesting[1].baz_method  
        end
      end

      def self.baz_method
        puts "foo!"
      end
    end
  end
end

In this situation, Module.nesting will give the following (when called in qux_method): [Foo::Bar::Baz::Qux, Foo::Bar::Baz, Foo::Bar, Foo]

Note though that this is not an unambiguous reference to Baz, but rather to whatever happens to be one level up in the module chain.

Upvotes: 2

Jörg W Mittag
Jörg W Mittag

Reputation: 369448

Constants are looked up first in the lexically enclosing module(s) and then up the inheritance chain.

module Foo
  module Bar
    module Baz
      class Qux
        def self.qux_method
          Baz.baz_method    
        end
      end
      def self.baz_method
      end
    end
  end
end

This will work, because the constant Baz will be first looked up in the lexically enclosing module (class) Qux, where it isn't found. The lookup continues in the lexically enclosing module Baz, where it also isn't found. Therefore, it will next be looked up in the lexically enclosing module Bar, where it is found and the search stops.

Note: you write in your title:

Ruby, Access parent/sibling module methods

This is wrong. These modules are neither parents nor siblings. There is no inheritance here. There is, in fact, no relationship between the modules at all. There is only a relationship between the constants and the modules: constants belong to modules.

The module declarations are lexically nested, but the modules themselves aren't.

Upvotes: 13

drhining
drhining

Reputation: 221

You don't need to specify the entire namespace chain. You only need as much as is necessary to disambiguate the constant. Just use Baz.baz_method.

module Foo
  module Bar
    module Baz
      class Qux
        def self.qux_method
          Baz.baz_method
        end
      end

      def self.baz_method
      end
    end
  end
end

Upvotes: 6

Related Questions