#!/usr/local/bin/ruby -w
#
# == extensions/module.rb
#
# Adds methods to the builtin Module class.
#
require "extensions/_base"
ExtensionsProject.implement(Module, :deep_const_get) do
class Module
#
# Recursively dereferences constants separated by "::".
#
# _const_ is a Symbol or responds to #to_str, for compatibility with the builtin method
# Module#const_get.
#
# Object.const_get("String") # -> String
# Object.const_get(:String) # -> String
#
# Object.deep_const_get("String") # -> String
# Object.deep_const_get(:String) # -> String
#
# Object.deep_const_get("Process::Sys") # -> Process::Sys
# Object.deep_const_get("Regexp::IGNORECASE") # -> 1
# Object.deep_const_get("Regexp::MULTILINE") # -> 4
#
# require 'test/unit'
# Test.deep_const_get("Unit::Assertions") # -> Test::Unit::Assertions
# Test.deep_const_get("::Test::Unit") # -> Test::Unit
#
# For resolving classes or modules based on their name, see Module.by_name, which uses this
# method.
#
def deep_const_get(const)
if Symbol === const
const = const.to_s
else
const = const.to_str.dup
end
if const.sub!(/^::/, '')
base = Object
else
base = self
end
const.split(/::/).inject(base) { |mod, name| mod.const_get(name) }
end
end
end
ExtensionsProject.implement(Module, :by_name, :class) do
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.get_const("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
#
def Module.by_name(name)
if Symbol === name
name = name.to_s
else
name = name.to_str
end
result = Object.deep_const_get(name)
if result.is_a? Module
return result
else
raise ArgumentError, "#{name} is not a class or module"
end
end
end
end
ExtensionsProject.implement(Module, :basename) do
class Module
#
# Returns the immediate name of the class/module, stripped of any containing classes or
# modules. Compare Ruby's builtin methods Module#name and File.basename.
#
# Process::Sys.name # -> "Process::Sys"
# Process::Sys.basename # -> "Sys"
# String.basename # -> "String"
#
def basename
self.name.sub(/^.*::/, '')
end
end
end