There are three ways in which the second version (A::B) differs from the first:
- It assumes that the outer module, i.e.
A is already defined. If it's not, Ruby will throw a NameError: uninitialized constant A error. So use this syntax only if you're sure that module A exists.
- It allows you to reduce the amount of indentation. Instead of 3 levels of indentation, only one is necessary.
- You can not access the constants defined inside module
A inside module B without the scope resolution (::) operator. This is a significant difference; the next section covers it in detail.
Accessing Constants in Nested Modules
The scope of constant access is different depending on how the nested module is defined. Let's consider the first version.
module A
Z = 10
module B
puts Z
end
end
# output
10
Let's try accessing the constant in a module defined using the second syntax. It throws a NameError.
module A
Z = 10
end
module A::B
puts Z
end
# output
uninitialized constant A::B::Z (NameError)
Here, you've to access it using the scope resolution operator (::) as follows:
module A
Z = 10
end
module A::B
puts A::Z
end
# output
10
Module Nesting
The Module.nesting method returns the list of modules nested at the time of call. The following example shows how the two versions differ in their module nesting.
module A
p Module.nesting # [A]
module B
p Module.nesting # [A::B, A]
end
module B::C
p Module.nesting # [A::B::C, A]
end
end
module A::D
p Module.nesting # [A::D]
end
When module D is defined, the nesting does not include module A. Hence, module D cannot access the constants defined in module A, without explicitly using the scope resolution (::) operator.
Source: Nested Modules in Ruby