@@ -21,44 +21,48 @@ def classify(dashed_word)
21
21
dashed_word . split ( '-' ) . each { |part | part [ 0 ] = part [ 0 ] . chr . upcase } . join
22
22
end
23
23
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.
25
25
#
26
- # constantize(" Module") # => Module
27
- # constantize(" Test::Unit") # => Test::Unit
26
+ # ' Module'.constantize # => Module
27
+ # ' Test::Unit'.constantize # => Test::Unit
28
28
#
29
29
# The name is assumed to be the one of a top-level constant, no matter
30
30
# whether it starts with "::" or not. No lexical context is taken into
31
31
# account:
32
32
#
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
39
39
#
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.
41
42
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 ( '::' )
49
44
names . shift if names . empty? || names . first . empty?
50
45
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 )
57
49
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 )
59
64
end
60
65
end
61
- constant
62
66
end
63
67
end
64
68
end
0 commit comments