Just finished the new O’Reilly Ruby book. It was mostly review but one thing I liked was their demonstration of constant name resolution. And I learned something new,
Module.nesting returns the lexically enclosing classes/modules which are searched before Ruby walks up the class/module hierarchy to find the constant. Here’s an example of how
Module.nesting doesn’t care about class hierarchy or namespaces, only lexical scope.
class A; end class B; end class C; end class C::D; end module E; end class X < A; end class Y < B; end class Z < C; end class ::X class ::Y class ::Z class ::C::D module ::M include E p Module.nesting end end end end end # => [M, C::D, Z, Y, X]
As you can see, the superclasses of X,Y,Z (A,B,C) are not present. The namespace of class D (C::) is not present either. Neither is the module E, which is included in M. Only the lexical nesting is returned.
The book has a good example which covers the entire lookup chain. Taken from The Ruby Programming Language:
module Kernel # Constants defined in Kernel A = B = C = D = E = F = "defined in kernel" end # Top-level or "global" constants defined in Object A = B = C = D = E = "defined at toplevel" class Super # Constants defined in a superclass A = B = C = D = "defined in superclass" end module Included # Constants defined in an included module A = B = C = "defined in included module" end module Enclosing # Constants defined in an enclosing module A = B = "defined in enclosing module" class Local < Super include Included # Locally defined constant A = "defined locally" # The list of modules searched, in the order searched # [Enclosing::Local, Enclosing, Included, Super, Object, Kernel] search = (Module.nesting + self.ancestors + Object.ancestors).uniq puts A # Prints "defined locally" puts B # Prints "defined in enclosing module" puts C # Prints "defined in included module" puts D # Prints "defined in superclass" puts E # Prints "defined at toplevel" puts F # Prints "defined in kernel" end end