Class: Root::Constant

Inherits:
Object
  • Object
show all
Defined in:
lib/root/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.



75
76
77
78
# File 'lib/root/constant.rb', line 75

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

Instance Attribute Details

#nameObject (readonly)

The constant name



68
69
70
# File 'lib/root/constant.rb', line 68

def name
  @name
end

#require_pathObject (readonly)

The path to load to initialize a missing constant



71
72
73
# File 'lib/root/constant.rb', line 71

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 desired constant; in the example ‘Non::Existant’ is effectively mapping to ConstName.

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/root/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.



117
118
119
120
121
# File 'lib/root/constant.rb', line 117

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

#basenameObject

Returns the basename of path.



86
87
88
# File 'lib/root/constant.rb', line 86

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

#const_nameObject

Returns the name of the constant, minus nesting.



96
97
98
# File 'lib/root/constant.rb', line 96

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, constantize requires require_path and tries again.

Raises a NameError if the constant cannot be found.



127
128
129
130
131
132
# File 'lib/root/constant.rb', line 127

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.



91
92
93
# File 'lib/root/constant.rb', line 91

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

#documentObject

Returns the Lazydoc document for require_path.



111
112
113
# File 'lib/root/constant.rb', line 111

def document
  require_path ? Lazydoc[require_path] : nil 
end

#inspectObject

Returns a string like:

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


136
137
138
# File 'lib/root/constant.rb', line 136

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

#nestingObject

Returns the nesting constants of name.



101
102
103
# File 'lib/root/constant.rb', line 101

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

#nesting_depthObject

Returns the number of constants in nesting.



106
107
108
# File 'lib/root/constant.rb', line 106

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

#pathObject

Returns the underscored name.



81
82
83
# File 'lib/root/constant.rb', line 81

def path
  @path ||= name.underscore
end