@@ -21,44 +21,48 @@ def classify(dashed_word)
2121 dashed_word . split ( '-' ) . each { |part | part [ 0 ] = part [ 0 ] . chr . upcase } . join
2222 end
2323
24- # Tries to find a constant with the name specified in the argument string:
24+ # Tries to find a constant with the name specified in the argument string.
2525 #
26- # constantize(" Module") # => Module
27- # constantize(" Test::Unit") # => Test::Unit
26+ # ' Module'.constantize # => Module
27+ # ' Test::Unit'.constantize # => Test::Unit
2828 #
2929 # The name is assumed to be the one of a top-level constant, no matter
3030 # whether it starts with "::" or not. No lexical context is taken into
3131 # account:
3232 #
33- # C = 'outside'
34- # module M
35- # C = 'inside'
36- # C # => 'inside'
37- # constantize("C") # => 'outside', same as ::C
38- # end
33+ # C = 'outside'
34+ # module M
35+ # C = 'inside'
36+ # C # => 'inside'
37+ # 'C'.constantize # => 'outside', same as ::C
38+ # end
3939 #
40- # NameError is raised when the constant is unknown.
40+ # NameError is raised when the name is not in CamelCase or the constant is
41+ # unknown.
4142 def constantize ( camel_cased_word )
42- camel_cased_word = camel_cased_word . to_s
43-
44- if camel_cased_word . include? ( '-' )
45- camel_cased_word = classify ( camel_cased_word )
46- end
47-
48- names = camel_cased_word . split ( '::' )
43+ names = camel_cased_word . to_s . split ( '::' )
4944 names . shift if names . empty? || names . first . empty?
5045
51- constant = Object
52- names . each do |name |
53- args = Module . method ( :const_get ) . arity != 1 ? [ false ] : [ ]
54-
55- if constant . const_defined? ( name , *args )
56- constant = constant . const_get ( name )
46+ names . inject ( Object ) do |constant , name |
47+ if constant == Object
48+ constant . const_get ( name )
5749 else
58- constant = constant . const_missing ( name )
50+ candidate = constant . const_get ( name )
51+ next candidate if constant . const_defined? ( name , false )
52+ next candidate unless Object . const_defined? ( name )
53+
54+ # Go down the ancestors to check it it's owned
55+ # directly before we reach Object or the end of ancestors.
56+ constant = constant . ancestors . inject do |const , ancestor |
57+ break const if ancestor == Object
58+ break ancestor if ancestor . const_defined? ( name , false )
59+ const
60+ end
61+
62+ # owner is in Object, so raise
63+ constant . const_get ( name , false )
5964 end
6065 end
61- constant
6266 end
6367 end
6468end
0 commit comments