2

I have a module structure like this:

module Parent

  PARENT_CONST = 'parent const'

  def Parent.meth
    puts 'parent meth'
  end

end

module Child
  include Parent
end

This works as expected:

puts Parent::PARENT_CONST
 => parent const
Parent.meth
 => parent meth

I can access the parent's constant from the child, but not the method. Like this:

Child::PARENT_CONST
 => parent const
Child.meth
 => in `<main>': undefined method `meth' for Child:Module (NoMethodError)

Is there a way for me to do this?

kdbanman
  • 10,161
  • 10
  • 46
  • 78
  • 1
    See https://stackoverflow.com/questions/13269271/why-a-modules-singleton-method-is-not-visible-in-downstream-eigenclasses-where – cremno Mar 22 '15 at 00:10

1 Answers1

5

The following is a common way to mix a module containing constants, instance methods, and class methods into a class, but it can also be used to include constants and class methods of one module in another module, which is what you want to do. It uses the "callback" or "hook" method Module#included. Object#extend adds the instance methods in the module that is the argument to the module that is extend's receiver. Below it makes the instance methods (here just one) in Public::C_Meths class methods in the module Child.

module Parent
  module I_Meths
    PARENT_CONST = 'parent const'
  end

  module C_Meths
    def cmeth
      'cmeth'
    end
  end

  def self.included(mod)
    mod.include(I_Meths)
    mod.extend(C_Meths)
  end
end

module Child
  include Parent
end

Child::PARENT_CONST
  #=> "parent const" 
Child.cmeth
  #=> "cmeth" 

It's more common to use this construct to mix a module containing constraints, instance methods and class methods into a class.

Suppose we were to add the instance method:

def imeth
  'imeth'
end

to the module Parent::I_Meths and include Parent in a class:

class A
  include Parent
end

then

A::PARENT_CONST
  #=> "parent const" 
A.cmeth
  #=> "cmeth" 
A.new.imeth
  #=> "imeth"
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100