Mixing in a constant from another module

I have a module B which gets mixed in to a module I, like this:

module B
BC = 4711
def g
puts ‘works’
end
end

module I
extend self
extend B
def f
g
puts B::BC
end
end

If I invoke

I.f

I get the output

works
4711

as expected. From I::f, I can invoke g directly, as if it had been
defined inside I, because I included B using extend B. For accessing the
constant BC, I have to qualify it explicitly, B::BC.

Is there a way I can access the constants in B from within I without
qualification with the module name?

I believe you need to both include & extend B for this to work.

Here is an example:

===========================
module B
BC = 4711

def g
puts ‘works’
end

def self.extended(base)
base.send(:include, self)
end
end

module I
extend self
extend B

def f
g
puts BC
end
end

I.f

Explanation:
When you use ‘extend’ everything is dumped into I’s singleton class, and
the singleton class is not part of the constant lookup path.

Notice that this will add an extra ‘g’ instance method to I’s public
interface.

If that’s a problem you could try separating the constants & the methods
like this:

===========================
module B
module Constants
BC = 4711
end
include Constants

def g
puts ‘works’
end

def self.extended(base)
base.send(:include, Constants)
end
end

I hope that helps :slight_smile:

  • Jesus Castello, blackbytes.info

I never had considered doing include AND extend together.

The complexity of the solution makes me wonder, whether what I want to
achieve is really still in “Ruby spirit”. Maybe my thinking was
influenced too much by other languages (C++ namespaces for instance). Am
I the (nearly) only one who wants to use modules in this way?

In any case: Thanks a lot! Your suggestions helps indeed.