Cannot access constants from included modules in a submodule

Hi there,

I am trying to include a bunch of constants into a module and all its
“submodules” (by this I mean modules that are defined within the scope
of the first module; is there a word for that?), but the constants only
seem accessible in the module that directly includes them, not in a
submodule. See this example:

===
module FooModule

Foo = :foo

end

module BarModule

include FooModule

Bar = :bar

p ancestors # => [BarModule, FooModule]
p Bar # works
p Foo # works

module SubBarModule

p ancestors # => [BarModule::SubBarModule]
p Bar # works
p Foo # fails

end

end

Now if the SubBarModule’s ancestors do not include FooModule, I can
understand that it cannot access Foo, but on the other hand,
SubBarModule’s ancestors do not include BarModule either, so why can it
acces Bar?

Tested in Ruby 1.8.7, 1.9.3p0 and 2.0.0p195, just to be sure that the
semantics have not changed – it seems to be they haven’t.

Regards,

Bram Senders
[email protected]

can you put the actual code in a gist or something to make it easier to
read.

Thanks,
Brad

Kendall G. wrote in post #1111199:

On Mon, Jun 3, 2013 at 9:38 AM, Bram S. [email protected] wrote:

Now if the SubBarModule’s ancestors do not include FooModule, I can
understand that it cannot access Foo, but on the other hand,
SubBarModule’s ancestors do not include BarModule either, so why can it
acces Bar?

“Constants are looked up in the lexical scope in which they were
referenced.” (Programming Ruby 1.9, page 290)

Accessing the constant Bar works above because the constant is available
based on the lexical scope (it’s defined in an enclosing module
definition). So, its availability has nothing to do with inheritance. If
you really want a set of constants to be available to a module and all
modules nested/namespaced within it, just define said constant in the
outermost module that needs access.

Okay, I see how this works now.

Thanks for your clarifications!

Bram Senders
[email protected]

On Mon, Jun 3, 2013 at 9:38 AM, Bram S. [email protected] wrote:

Hi there,

I am trying to include a bunch of constants into a module and all its
“submodules” (by this I mean modules that are defined within the scope
of the first module; is there a word for that?),

I would just say that your “submodules” are “namespaced” or “nested”
within
a parent.

module SubBarModule
Now if the SubBarModule’s ancestors do not include FooModule, I can
understand that it cannot access Foo, but on the other hand,
SubBarModule’s ancestors do not include BarModule either, so why can it
acces Bar?

“Constants are looked up in the lexical scope in which they were
referenced.” (Programming Ruby 1.9, page 290)

Accessing the constant Bar works above because the constant is available
based on the lexical scope (it’s defined in an enclosing module
definition). So, its availability has nothing to do with inheritance. If
you really want a set of constants to be available to a module and all
modules nested/namespaced within it, just define said constant in the
outermost module that needs access. If the constants are already defined
in
another, unrelated module that gets mixed into the outermost module,
like
you’re doing by including FooModule into BarModule, and if moving the
constants directly into FooModule isn’t an option, then there are
several
other options; which is best really depends upon the specifics of your
circumstances.