Why doesn't Ruby find classes in a higher scope when a module is specified with ::?

I just got stuck on this for a while. Take this base:

module Top class Test end module Foo end end 

Later, I can define classes inside Foo that extend Test by doing this:

 module Top module Foo class SomeTest < Test end end end 

However, if I try to minimize indentation by using :: to indicate the module:

 module Top::Foo class Failure < Test end end 

This fails:

NameError: uninitialized constant Top :: Foo :: Test

Is this a mistake, or is it just a logical consequence of how Ruby resolves variable names?

+5
source share
2 answers

Is this a mistake or is it just a logical consequence

This is a "fad." Some consider this a mistake.

Parent areas used to search for unresolved constants are determined by nesting the modules. It so happened that when using module Top::Foo it creates only one level of nesting instead of two. Note:

 module Top module Foo class SomeTest Module.nesting # => [Top::Foo::SomeTest, Top::Foo, Top] end end end module Top::Foo class SomeTest Module.nesting # => [Top::Foo::SomeTest, Top::Foo] end end 
+7
source

Expected. Using :: changes the scope of the constant search and expects Test be defined in Top::Foo .

To get the expected result, you can write:

 module Top::Foo class SomeTest < Top::Test end end 

or

 module Top class Foo::SomeTest < Test end end 

or even:

 class Top::Foo::SomeTest < Top::Test end 
+1
source

Source: https://habr.com/ru/post/1238534/


All Articles