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 extends Test by doing this:
module Top
  module Foo
    class SomeTest < Test
    end
  end
end
However, if I try to minimize indentation by using :: to specify the module:
module Top::Foo
  class Failure < Test
  end
end
This fails with:
NameError: uninitialized constant Top::Foo::Test
Is this a bug, or is it just a logical consequence of the way Ruby resolves variable names?
Is this a bug, or is it just a logical consequence
It's a "quirk". Some consider it a bug.
Parent scopes used for looking up unresolved constants are determined by module nesting. It just so happens that when you use module Top::Foo, it creates just one level of nesting instead of two. Observe:
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
                        This is expected. Using :: changes the scope of constant lookup and expects Test to be defined under Top::Foo.
To get the expected result, you could 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
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With