From: ara.t.howard@... Date: 2006-04-08T03:29:22+09:00 Subject: Re: autorequire.rb On Sat, 8 Apr 2006, zdennis wrote: > -----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 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 -- be kind whenever possible... it is always possible. - h.h. the 14th dali lama