David Masover
8/16/2008 8:29:00 PM
On Saturday 16 August 2008 12:55:42 David Masover wrote:
> On Saturday 16 August 2008 07:33:22 Trans wrote:
>
> > It is a serious issue with one of
> > my programs. Because of it I am forced never to use autoload, and tell
> > all users of my program that they must do the same.
>
> I think I've found a solution, for myself -- basically a const_missing hack.
Ok, that didn't work. All kinds of edge cases, and I can see why things like
autoload have been written.
So I wrote my own... but there's still one problem I can't seem to solve here:
class AutoLoader < BasicObject
def initialize parent, mod, file
@parent, @mod, @file = parent, mod, file
end
end
# Pushed out here so I can get at Kernel.require.
AutoLoader.send :define_method, :method_missing do |*args, &block|
@parent.send :remove_const, @mod
Kernel.require @file
@parent.const_get(@mod).send *args, &block
end
Typical usage would be:
self.class.const_set :Foo, AutoLoader.new(self.class, :Foo, 'foo')
And it works great -- exactly the way I want -- for _almost_ all cases.
I still can't do this:
module Foo
end
without actually loading foo.rb yet. (Somehow, Ruby knows my BasicObject isn't
a module, without ever tripping the method_missing there.)
Yet the same thing _does_ work with autoload:
autoload :Foo, 'foo'
module Foo; end
For what it's worth, Rails' const_missing has an even worse problem: If I do
the "module Foo" syntax above, I will define Foo, which means const_missing
will never be triggered, which means foo.rb will never be loaded.
It looks like my choices are either to learn to write a (non-portable) C
extension (and maybe still not have it work?), or to create a temporary file,
point autoload at that, and have it do the rest.
That sucks.
Is there any way to know for certain when a file is loaded, when it's autoload
that's doing it, short of modifying the file? (I'm specifically wanting to be
_notified_, so that I can prepare sub-constants to be autoloaded as well --
that is, when Foo is loaded, I want to automatically run Foo.autoload :Bar.)
Is there any way to force autoload to use a different mechanism?
Is there any way, in Ruby, to emulate autoload with actual feature parity?
Or am I really going to have to create a temporary file for each and every
source file I might possibly ever want to use?