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
···
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
--
be kind whenever possible... it is always possible.
- h.h. the 14th dali lama