public
Description: General Ruby extensions for DataMapper and DataObjects
Homepage:
Clone URL: git://github.com/sam/extlib.git
Fixed Module#find_const to raise NameError when sibling not found [#478 
state:resolved]

* Refactored Module#find_const to be much simpler internally
Dan Kubb (author)
Wed Jul 23 00:10:32 -0700 2008
commit  046a9005dd97d46e5c69db414a5fabe50a7f551d
tree    7e73c25ae93d4b74d8814a33131bc6163f4e9219
parent  a2a3b15058b2363438385c3116caaead3737306d
...
1
2
3
4
 
 
 
5
6
7
8
9
10
 
11
12
13
14
 
 
15
16
17
18
19
 
 
20
21
22
23
24
25
26
 
 
 
27
28
29
30
31
32
33
34
 
 
 
 
 
 
 
 
35
36
37
38
39
40
41
 
 
42
43
44
...
1
 
 
 
2
3
4
5
 
 
 
 
 
6
7
8
9
 
10
11
12
 
 
 
 
13
14
15
 
 
 
 
 
 
16
17
18
19
 
20
21
 
 
 
 
22
23
24
25
26
27
28
29
30
 
31
32
 
 
 
33
34
35
36
37
0
@@ -1,44 +1,37 @@
0
 class Module
0
-  def find_const(nested_name)
0
-    if nested_name =~ /^\:\:/
0
-      Object::__nested_constants__(nested_name)
0
+  def find_const(const_name)
0
+    if const_name[0..1] == '::'
0
+      Object.find_const(const_name[2..-1])
0
     else
0
-      begin
0
-        self.__nested_constants__(nested_name)
0
-      rescue NameError
0
-        Object::__nested_constants__(nested_name)
0
-      end
0
+      nested_const_lookup(const_name)
0
     end
0
   end
0
 
0
-protected
0
+  private
0
+
0
   # Doesn't do any caching since constants can change with remove_const
0
-  def __nested_constants__(k)
0
-    klass = self
0
-    modules = [Object]
0
-    keys = k.split('::')
0
+  def nested_const_lookup(const_name)
0
+    constants = [ Object ]
0
 
0
-    if keys.first.blank? # We got "::Foo::Bar", so we'll get rid of the opening '::', and only search Object
0
-      keys.shift
0
-    else
0
-      klass.name.split('::').inject(modules) do |ary, elem|
0
-        ary << ary.last.const_get(elem)
0
-        ary
0
+    unless self == Object
0
+      self.name.split('::').each do |part|
0
+        constants.unshift(constants.first.const_get(part))
0
       end
0
-      modules.reverse!
0
     end
0
 
0
-    modules.each do |m|
0
-      keys.inject(m) do |group, elem|
0
-        break unless group.const_defined?(elem)
0
-        klass = group.const_get(elem)
0
+    parts = const_name.split('::')
0
+
0
+    # from most to least specific constant, use each as a base and try
0
+    # to find a constant with the name const_name within them
0
+    constants.each do |const|
0
+      # return the nested constant if available
0
+      return const if parts.all? do |part|
0
+        const = const.const_defined?(part) ? const.const_get(part) : nil
0
       end
0
-      break unless klass == self
0
     end
0
 
0
-    raise NameError if klass == Object
0
-
0
-    klass
0
+    # if we get this far then the nested constant was not found
0
+    raise NameError
0
   end
0
 
0
 end # class Module
...
23
24
25
26
 
 
27
28
29
30
 
31
32
33
34
35
36
37
38
39
40
 
41
42
43
...
23
24
25
 
26
27
28
29
30
 
31
32
33
34
 
 
 
 
 
 
 
35
36
37
38
0
@@ -23,21 +23,16 @@ describe Module do
0
   end
0
 
0
   it "should raise NameError for a missing constant" do
0
-    lambda { Object::find_const('MissingConstant') }.should raise_error(NameError)
0
+    lambda { Foo.find_const('Moo') }.should raise_error(NameError)
0
+    lambda { Object.find_const('MissingConstant') }.should raise_error(NameError)
0
   end
0
 
0
   it "should be able to get a recursive constant" do
0
-    Object::find_const('Foo::Bar').should == Foo::Bar
0
+    Object.find_const('Foo::Bar').should == Foo::Bar
0
   end
0
 
0
   it "should ignore get Constants from the Kernel namespace correctly" do
0
-    Object::find_const('::Foo::Bar').should == ::Foo::Bar
0
-  end
0
-
0
-  it "should not cache unresolvable class string" do
0
-    pending "This shouldn't be applicable anymore, but hopefully somebody can double check before it is removed"
0
-    lambda { find_const('Foo::Bar::Baz') }.should raise_error(NameError)
0
-    Object::send(:__nested_constants__).has_key?('Foo::Bar::Baz').should == false
0
+    Object.find_const('::Foo::Bar').should == ::Foo::Bar
0
   end
0
 
0
   it "should find relative constants" do

Comments