# 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