Forum: Ruby Cannot access constants from included modules in a submodule

9817f7d98dbed4ef6e8bd0e987e091fa?d=identicon&s=25 Bram S. (bram_s)
on 2013-06-03 17:38
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
bupknar@gmail.com
Bf7b52be4eb5664df994184ddf1fed6e?d=identicon&s=25 Brad Smith (bradleyd)
on 2013-06-03 22:06
(Received via mailing list)
can you put the actual code in a gist or something to make it easier to
read.

Thanks,
Brad
94cee02d73877ef5e6dfb04afb1fe324?d=identicon&s=25 Kendall Gifford (zettabyte)
on 2013-06-03 22:37
(Received via mailing list)
On Mon, Jun 3, 2013 at 9:38 AM, Bram S. <lists@ruby-forum.com> 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.
9817f7d98dbed4ef6e8bd0e987e091fa?d=identicon&s=25 Bram S. (bram_s)
on 2013-06-05 13:56
Kendall Gifford wrote in post #1111199:
> On Mon, Jun 3, 2013 at 9:38 AM, Bram S. <lists@ruby-forum.com> 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
bupknar@gmail.com
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.