nub
nub

Reputation: 474

How to call namespace method on namespaced class in Ruby

I'm writing some class inside module:

module A
end

module A::B
  def foo
    print "foo"
  end
end

class A::B::C
end

A::B::C.new.foo # => NoMethodError: undefined method `foo' for #<A::B::C...>

How can I define method in module B to call in the class C?

Upvotes: 2

Views: 4696

Answers (3)

Andrew Marshall
Andrew Marshall

Reputation: 97024

Namespaces in Ruby don’t work the way you seem to think.

  1. There is no such thing as a “namespace method”. A::B#foo is an instance method on the module A::B—which is a module named B in the namespace of A.

  2. Namespaces modules/classes have no special relationship of inheritance between them. They are purely organizational in nature, except when defined the long way (e.g. module A; module B; end; end) when they can affect lexical scope.

If you want to get methods of A::B in A::B::C, you must include A::B in A::B::C, just like you would anywhere else. You have to do this because, as said above, there's nothing special about a namespaced module/class, it is treated the same as any other.

Upvotes: 3

BernardK
BernardK

Reputation: 3744

It is as if you write:

module A::B
  def foo
    print "foo"
  end

  class C
  end
  print 'C.instance_methods : '; p C.instance_methods(false)
  #=> C.instance_methods : []
end

C does not automatically inherits foo. There are only two ways to inherit instance methods:

  1. class C < super_class where super_class is an expression returning a class

  2. Including a module:

    class C
      include <some module>
    

For an explanation of the superclass chain, see How does Inheritance work in Ruby? and Ruby: Module, Mixins and Blocks confusing?

Upvotes: 4

sawa
sawa

Reputation: 168269

class A::B::C
  include A::B
end

Upvotes: 2

Related Questions