Monday, 2 September 2013

Ruby nested modules as namespaces

Ruby nested modules as namespaces

I have a nested structure of modules, which are used only for namespacing
purposes; no mixing into classes etc. So I have a code like this:
module Lib
module A
def A.foo
puts 'Lib::A::foo'
end
end
module B
def B.bar
puts 'Lib::B::bar'
end
end
end
Now suppose I want to add one more helper method in module A, and I want
it to be used easily by both modules. I get the following:
module Lib
module A
def A.foo
puts 'Lib::A::foo'
end
def A.helper
puts 'Lib::A::helper'
end
end
module B
def B.bar
puts 'Lib::B::bar'
A::helper
end
end
end
and it seems to work, but it has some drawback I'd like to get rid of:
I don't want to call helper by its full qualified name (A::helper) all the
time from inside B. I'd prefer to tell Ruby somehow that this namespace
prefix is "default" and call it simply as helper. In C++ I could just
write using A::helper inside namespace B and it would solve the problem.
But how to do it in Ruby?
I tried adding include A and extend A inside B, but none of them works.
They seem to work only inside classes, when these modules are mixed in,
but not when they're stand-alone, used just for namespacing purposes.
Are there any other ways to make it work the way I want?
Oh, and one more thing:
Suppose a different scenario, where I want the A::helper to be used only
from inside A's methods, because it's just some implementation function,
where I factored out some common code used by many functions inside A, but
now I don't want it to be visible for the outside world, just to A's
methods. How can I do it?
I tried with module_function + removing the A. prefix from all other
functions which are supposed to be hidden, but then they're hidden also
for other methods in A, because they're instance methods then, and modules
cannot be instantiated. So how can I hide a module method from outside
world and still allow it for the internal use by other module methods?

No comments:

Post a Comment