# TITLE: # # Name # # DESCRIPTION: # # Extensions related to module names and namespace. # # COPYRIGHT: # # Copyright (c) 2007 Gavin Sinclair, Thomas Sawyer # Distributed under the terms of the Ruby License # # AUTHORS: # # - Gavin Sinclair # - Thomas Sawyer # class Module # Note: the following documentation uses "class" because it's more common, but it # applies to modules as well. # # Given the _name_ of a class, returns the class itself (i.e. instance of Class). The # dereferencing starts at Object. That is, # # Class.by_name("String") # # is equivalent to # # Object.const_get("String") # # The parameter _name_ is expected to be a Symbol or String, or at least to respond to # to_str. # # An ArgumentError is raised if _name_ does not correspond to an existing class. If _name_ # is not even a valid class name, the error you'll get is not defined. # # Examples: # # Class.by_name("String") # -> String # Class.by_name("::String") # -> String # Class.by_name("Process::Sys") # -> Process::Sys # Class.by_name("GorillaZ") # -> (ArgumentError) # # Class.by_name("Enumerable") # -> Enumerable # Module.by_name("Enumerable") # -> Enumerable # #-- # Credit for this goes to Gavin Sinclair. #++ def by_name(name) #result = Object.constant(name) # ??? Does self need to be Object in the following lines? const = name.to_s.dup base = const.sub!(/^::/, '') ? Object : ( self.kind_of?(Module) ? self : self.class ) result = const.split(/::/).inject(base){ |mod, name| mod.const_get(name) } return result if result.kind_of?( Module ) raise ArgumentError, "#{name} is not a module or class" end # Returns the root name of the module/class. # # module Example # class Demo # end # end # # Demo.name #=> Example::Demo # Demo.basename #=> Demo # # For anonymous modules this will provide a basename # based on Module#inspect. # # m = Module.new # m.inspect #=> "#" # m.basename #=> "Module_0xb7bb0434" # def basename if name and not name.empty? name.gsub(/^.*::/, '') else nil #inspect.gsub('#<','').gsub('>','').sub(':', '_') end end # Returns the name of module's container module. # # module Example # class Demo # end # end # # Demo.name #=> "Example::Demo" # Demo.dirname #=> "Example" # # See also Module#basename. # def dirname name[0...(name.rindex('::') || 0)] #name.gsub(/::[^:]*$/, '') end # Returns the module's container module. # # module Example # class Demo # end # end # # Demo.modspace #=> Example # # See also Module#basename. # def modspace space = name[ 0...(name.rindex( '::' ) || 0)] space.empty? ? Object : eval(space) end #-- # Special thanks to Mauricio Fernandez # parent = Object.const_get(mod.to_s.sub(/::[^:]+\z/, "")) #++ def nesting n = [] name.split(/::/).inject(self){ |mod, name| c = mod.const_get(name) ; n << c ; c } return n end end =begin test require 'test/unit' class TestModuleName < Test::Unit::TestCase def test_ancestor assert( self.class.ancestor?(::Test::Unit::TestCase) ) end def test_by_name c = ::Test::Unit::TestCase.name assert_equal( ::Test::Unit::TestCase, Module.by_name(c) ) c = "Test::Unit::TestCase" assert_equal( ::Test::Unit::TestCase, Class.by_name(c) ) end def test_basename assert_equal( "TestCase", ::Test::Unit::TestCase.basename ) end def test_dirname assert_equal( 'Test::Unit', Test::Unit::TestCase.dirname ) assert_equal( 'Test::Unit', ::Test::Unit::TestCase.dirname ) assert_equal( '', Test.dirname ) assert_equal( '', ::Test.dirname ) end def test_modspace assert_equal( Test::Unit, Test::Unit::TestCase.modspace ) assert_equal( ::Test::Unit, ::Test::Unit::TestCase.modspace ) assert_equal( Object, ::Test.modspace ) end module M module N class C def n self.class.nesting end end end end def test_nesting assert_equal( [TestModuleName, M, M::N, M::N::C], M::N::C.new.n ) end end =end