Class: Tap::Support::Constant

Inherits:
Object
  • Object
show all
Defined in:
lib/tap/support/constant.rb

Overview

A Constant serves as a placeholder for an actual constant, sort of like autoload. Use the constantize method to retrieve the actual constant; if it doesn’t exist, constantize requires require_path and tries again.

Object.const_defined?(:Net)                      # => false
$".include?('net/http')                          # => false

http = Constant.new('Net::HTTP', 'net/http')
http.constantize                                 # => Net::HTTP
$".include?('net/http')                          # => true

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, require_path = nil) ⇒ Constant

Initializes a new Constant with the specified constant name and require_path. The name should be a valid constant name.



77
78
79
80
# File 'lib/tap/support/constant.rb', line 77

def initialize(name, require_path=nil)
  @name = name
  @require_path = require_path
end

Instance Attribute Details

#nameObject (readonly)

The constant name



69
70
71
# File 'lib/tap/support/constant.rb', line 69

def name
  @name
end

#require_pathObject (readonly)

The path to load to initialize a missing constant



72
73
74
# File 'lib/tap/support/constant.rb', line 72

def require_path
  @require_path
end

Class Method Details

.constantize(const_name, base = Object) ⇒ Object

Tries to find a declared constant under base with the specified const_name. When a constant is missing, constantize yields the current base and any non-existant constant names the block, if given, or raises a NameError. The block is expected to return the proper constant.

module ConstName; end

Constant.constantize('ConstName')                     # => ConstName
Constant.constantize('Non::Existant') { ConstName }   # => ConstName


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/tap/support/constant.rb', line 31

def constantize(const_name, base=Object) # :yields: base, missing_const_names
  unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ const_name
    raise NameError, "#{const_name.inspect} is not a valid constant name!"
  end
  
  constants = $1.split(/::/)
  while !constants.empty?
    unless const_is_defined?(base, constants[0])
      if block_given? 
        return yield(base, constants)
      else
        raise NameError.new("uninitialized constant #{const_name}", constants[0]) 
      end
    end
    base = base.const_get(constants.shift)
  end
  base
end

Instance Method Details

#==(another) ⇒ Object

True if another is a Constant with the same name and require_path as self.



119
120
121
122
123
# File 'lib/tap/support/constant.rb', line 119

def ==(another)
  another.kind_of?(Constant) && 
  another.name == self.name &&
  another.require_path == self.require_path
end

#basenameObject

Returns the basename of path.



88
89
90
# File 'lib/tap/support/constant.rb', line 88

def basename
  @basename ||= File.basename(path)
end

#const_nameObject

Returns the name of the constant, minus nesting.



98
99
100
# File 'lib/tap/support/constant.rb', line 98

def const_name
  @const_name ||= (name =~ /.*::(.*)$/ ? $1 : name)
end

#constantizeObject

Looks up and returns the constant indicated by name. If the constant cannot be found, the constantize requires require_path and tries again.

Raises a NameError if the constant cannot be found.



130
131
132
133
134
135
# File 'lib/tap/support/constant.rb', line 130

def constantize
  Constant.constantize(name) do
    require require_path if require_path
    Constant.constantize(name)
  end
end

#dirnameObject

Returns the path, minus the basename of path.



93
94
95
# File 'lib/tap/support/constant.rb', line 93

def dirname
  @dirname ||= (dirname = File.dirname(path)) == "." ? "" : dirname
end

#documentObject

Returns the Lazydoc document for require_path.



113
114
115
# File 'lib/tap/support/constant.rb', line 113

def document
  require_path ? Lazydoc[require_path] : nil 
end

#inspectObject

Returns a string like:

"#<Tap::Support::Constant:object_id Const::Name (require_path)>"


139
140
141
# File 'lib/tap/support/constant.rb', line 139

def inspect
  "#<#{self.class}:#{object_id} #{name}#{@require_path == nil ? "" : " (#{@require_path})"}>"
end

#nestingObject

Returns an array of the nesting constants of name.



103
104
105
# File 'lib/tap/support/constant.rb', line 103

def nesting
  @nesting ||= (name =~ /(.*)::.*$/ ? $1 : '')
end

#nesting_depthObject

Returns the number of constants in nesting.



108
109
110
# File 'lib/tap/support/constant.rb', line 108

def nesting_depth
  @nesting_depth ||= nesting.split(/::/).length
end

#pathObject

Returns the underscored name.



83
84
85
# File 'lib/tap/support/constant.rb', line 83

def path
  @path ||= name.underscore
end