The keywords class, module and def are what is known as "scope gates". They create new scopes.
#!/usr/bin/env ruby
module ModuleA
class ClassA
def initialize
puts "test passed"
end
end
end
module ModuleB
include ModuleA
# test 1
c = ClassA.new # this works as ModuleA has been included into this module
class ClassB # class is a scope gate, creates new scope
def initialize # def is a scope gate, creates new scope
c = ModuleA::ClassA.new # must fully qualify ClassA
end
end
ClassB2 = Class.new do # no scope gate
define_method :initialize do # no scope gate
c = ClassA.new # this works, no need to fully qualify
end
end
end
b = ModuleB::ClassB.new
b2 = ModuleB::ClassB2.new
I began to understand scopes in Ruby after reading the book "Metaprogramming Ruby". It is truly enlightening.
Edit: In response to also's comment below.
A class is essentially a Ruby constant (notice that it is an object with a capitalized name). Constants have a defined lookup algorithm within scopes. The Ruby Programming Language O'Reilly book explains it well in section 7.9. It is also briefly described in this blog post.
Top-level constants, defined outside of any class or module, are like top-level methods: they are implicitly defined in Object. When a top-level constant is referenced from within a class it is resolved during the search of the inheritance hierarchy. If the constant is referenced within a module definition it does an explicit check of Object after searching the ancestors of the module.
That's why include ModuleB at the top level makes the class in ModuleB visible in all modules, classes and methods.