# Autorequire.rb

**URL:** <https://www.ruby-forum.com/t/autorequire-rb/93729>\
**Category:** Ruby\
**Created:** [April 7, 2006, 5:40pm UTC](https://www.ruby-forum.com/t/autorequire-rb/93729 "2006-04-07T17:40:57Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [April 7, 2006, 5:40pm UTC](https://www.ruby-forum.com/t/autorequire-rb/93729/1 "2006-04-07T17:40:57Z")

</div>

just hacked this out - can anyone see holes in it?

```
 harp:~ > cat autorequire.rb
 class Module
   alias_method "const_missing!", "const_missing"
   def const_missing c
     lib4 = lambda{|k| k.to_s.downcase.gsub(%r/::/, 

```

File::SEPARATOR)}  
lib = Object == self ? lib4[c] : lib4["#{ name }::#{ c }"]  
begin; require lib; rescue LoadError; end  
const\_missing! c unless const\_defined? c  
const\_get c  
end  
end

```
 if $0 == __FILE__
   p Object
   p CGI
   p CGI::Session
   p PStore
   p K
 end

 harp:~ > ruby autorequire.rb
 Object
 CGI
 CGI::Session
 PStore
 autorequire.rb:7:in `const_missing': uninitialized constant K 

```

(NameError)  
from autorequire.rb:17

regards.

-a

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [April 7, 2006, 6:33pm UTC](https://www.ruby-forum.com/t/autorequire-rb/93729/2 "2006-04-07T18:33:12Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1

Depending on how smart you want it to be it will fail on stdlib’s that  
don’t follow a consistent downcase/spelling naming  
convention, ie: ostruct =\> OpenStruct

It doesn’t work with files which don’t have a toplevel file to include,  
like ‘net/ssh’. There is no ‘net’ file to load like there  
is with ‘cgi’ in ‘cgi/session’. Although I can’t think of a way OTOH to  
get around this with const\_missing, since you’ll never see  
the SSH part of Net::SSH because it will fail on Net.

Zach

removed\_email\_address@domain.invalid wrote:

> ```
> lib = Object == self ? lib4[c] : lib4["#{ name }::#{ c }"]
> p PStore
> autorequire.rb:7:in `const_missing': uninitialized constant K
> 
> ```
> 
> (NameError)  
> from autorequire.rb:17
> 
> regards.
> 
> -a

-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1.4.1 (GNU/Linux)  
Comment: Using GnuPG with Thunderbird - [http://enigmail.mozdev.org](http://enigmail.mozdev.org)

iD8DBQFENpRwMyx0fW1d8G0RAlDMAJ9GRGbwAEG3nbyH2t4FYdVx7WmVIwCdGAdb  
IN5Qznuop52w7ClovrY7mvM=  
=AW3I  
-----END PGP SIGNATURE-----

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [April 7, 2006, 8:32pm UTC](https://www.ruby-forum.com/t/autorequire-rb/93729/3 "2006-04-07T20:32:33Z")

</div>

On Sat, 8 Apr 2006, zdennis wrote:

> Zach  
> this is a possible workaround - it’s broken for some cases now but i’m  
> just  
> trying to show it’s possible :

```
 harp:~ > ruby a.rb

 {"Net"=>"ConstProxy(Net)"}
 {"Net::FTP"=>Net::FTP}

 harp:~ > cat a.rb

 require 'pp'

 autorequire 'Net::FTP' => 'net/ftp'

 pp 'Net' => Net
 pp 'Net::FTP' => Net::FTP

 BEGIN {
   require 'enumerator'

   class Module
     alias_method "const_missing!", "const_missing"

     def const_missing c
       c = c.to_s

       if autorequire.has_key? c
         obj = autorequire[c]
         cp = obj.respond_to?('ancestors') and 

```

obj.ancestors.include?(ConstProxy)  
if cp  
return obj  
else  
libs = obj  
libs.each{|lib| begin; require lib; rescue LoadError;  
end}  
end  
else  
lib4 = lambda{|k| k.to\_s.downcase.gsub(%r/::/,  
File::SEPARATOR)}  
lib = Object == self ? lib4[c] : lib4["#{ name }::#{ c }"]  
begin; require lib; rescue LoadError; end  
end

```
       if ancestors.include?(ConstProxy)
         to_const.const_get c
       else
         const_missing! c unless const_defined? c
         const_get c
       end
     end

     def autorequire c = nil, *libs
       if c
         h = Hash === c ? c : {c => libs}
         h.each do |c,libs|
           if c =~ %r/::/
           # hack for two deep nesting only
             k,v = c.split %r/::/
             cp = ConstProxy(k)
             autorequire[k] = cp
             cp.autorequire[v] = libs
           else
             autorequire[c.to_s] = [libs].flatten
           end
         end
         self
       else
         @autorequire ||= {}
       end
     end
   end

   module ConstProxy
     def self.new name
       name = name.to_s
       raise ArgumentError unless name =~ %r/^[A-Z]/
       Module.new do
         include ConstProxy
         singleton_klass =
           class << self; self; end
         singleton_klass.module_eval do
           define_method('name'){ name }
           define_method('to_s'){ "ConstProxy(#{ name })" }
           define_method('inspect'){ "\"#{ to_s }\"" }
           define_method('to_const'){ Object.const_get(name) }
         end
       end
     end
     module ::Kernel
       def ConstProxy(*a, &b) ConstProxy.new(*a, &b) end
     end
   end

   class Object
     def autorequire(*a, &b)
       self.class.autorequire(*a, &b)
     end
   end
 }

```

i’ll keep hacking on it and try to release something soon…

-a
