[ANN] autoloader, version 0.0.2

D

David Masover

A couple of handy features to enhance Kernel#autoload.

Changes since 0.0.1: minor tweaks to the gem, and migrated to gemcutter.

Question: How do I add a choice of dependencies? Right now, I can use either
extlib or activesupport for inflections.

Also: This is my first ever ruby-talk announcement. Someone please tell me if
I am Doing It Wrong.


Pasted from the README:


Features
========

* Fire Kernel#autoload at an entire directory
* Fire it again at a subdirectory, for namespace'd models


Motivation/Examples
===================

I was using Ramaze as a web framework, and discovered that the standard Ramaze
way of loading a directory of files is to slurp them all (with 'acquire'). I
decided I'd rather use autoload, and not load things I'm not using. But I
wasn't really looking forward to this:

autoload :User, 'model/user'
autoload :Clan, 'model/clan'
autoload :Item, 'model/item'

...ad nauseum. So, the first feature is a shallow, directory-based autoload:

AutoLoader << 'model'

Of course, being a pedant, I like to namespace my models. I don't want to
slurp the entire directory tree. Instead, you can do this:

class User < MyFavoriteORM::Model
include AutoLoader
...
end

Now, all AutoLoaded paths will be searched for a subdirectory called 'user',
and all files within will be autoloaded. Just as if you'd done:

User.autoload :Anonymous, 'model/user/anonymous'
User.autoload :Registered, 'model/user/registered'

Of course, there's no requirement that you have a base class, or anything of
the sort. If you just want a namespace, you can always do:

module MyNamespace; include AutoLoader; end

And you're done.


Compatibility
=============

Currently, Merb's extlib and Rails' activesupport are supported. It should be
trivial to interface with other libraries.
 
R

Robert Klemme

2009/11/24 David Masover said:
A couple of handy features to enhance Kernel#autoload.

Changes since 0.0.1: minor tweaks to the gem, and migrated to gemcutter.

Question: How do I add a choice of dependencies? Right now, I can use either
extlib or activesupport for inflections.

Also: This is my first ever ruby-talk announcement. Someone please tell me if
I am Doing It Wrong.

Looks fine to me. But I do wonder how you generate the symbol names
for autoload files? Basically autoload needs a symbol name and a file
name. While the file names can be extracted from a directory how do
you find the symbol name? Maybe users should be able to customize
that algorithm in order to be able to autoload class "FooBar" from
file "foobar.rb" or "foo_bar.rb". I would at least add a description
how you generate the symbol name from the file name.

Btw, one disadvantage of using a directory glob is that it is far more
expensive than the standard autoload because the standard autoload
does not need any file system IO before any file is loaded. Using
directory globbing on the other hand requires to at least read the
directory which may slow down startup of a script considerably.

Kind regards

robert
 
R

Rick DeNatale

A couple of handy features to enhance Kernel#autoload.

Changes since 0.0.1: minor tweaks to the gem, and migrated to gemcutter.

Question: How do I add a choice of dependencies? Right now, I can use either
extlib or activesupport for inflections.

As far as I know, you can't.

I've got a similar situation with ri_cal which needs either
activesupport or tzinfo. I asked about this on the rubygems list and
alternate dependencies seemed to be something which had come up from
time to time but hadn't been addressed.

I just didn't declare either as a dependency and rely on documentation
to let users know that they need one or the other.


--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
 
D

David Masover

Looks fine to me. But I do wonder how you generate the symbol names
for autoload files? Basically autoload needs a symbol name and a file
name. While the file names can be extracted from a directory how do
you find the symbol name?

More or less the same way Rails does, which is why I support these various
inflection libraries. Basically, I take the file name and munge it so it looks
like a constant name.
Maybe users should be able to customize
that algorithm in order to be able to autoload class "FooBar" from
file "foobar.rb" or "foo_bar.rb".

Right now, it's specified to be foo_bar.rb. It uses String#to_const_string
from extlib, or String#camelize from ActiveSupport. If neither of these are
loaded, it tries to load extlib, then activesupport/inflector.

Maybe users should be able to customize it. The idea is, of course, convention
over configuration. If there's only a single exception (FooBar, for example),
you could always manually autoload that one file.
I would at least add a description
how you generate the symbol name from the file name.

Neither of these are bad ideas.

If you can think of a way to customize the behavior without overcomplicating
things, go for it. I'm not motivated, so patches welcome.
Btw, one disadvantage of using a directory glob is that it is far more
expensive than the standard autoload because the standard autoload
does not need any file system IO before any file is loaded. Using
directory globbing on the other hand requires to at least read the
directory which may slow down startup of a script considerably.

Except that standard autoload is more work for me, and nearly defeats the
point. Trading requires for autoloads directly makes things harder to debug
without making them easier to write -- it _only_ optimizes start time.

One possibility would be to write a script which attempts to automatically
generate these autoload statements, but store them statically in a single
file. The main reason I don't like that is, you've now added a "compile" step
to a script. It might work as an option, maybe a "development" vs "production"
mode.

Another possibility is to override const_missing, but that gets complex fast,
as Rails shows.

Also, keep in mind that the directory IO is shallow. That is, if you tell it
to autoload foo, it won't touch anything in foo/bar. If you create a file
bar.rb which requires autoload, it will look at foo/bar, but only once Bar is
autoloaded.

Thanks for the feedback!
 
R

Robert Klemme

Except that standard autoload is more work for me, and nearly defeats the
point. Trading requires for autoloads directly makes things harder to debug
without making them easier to write -- it _only_ optimizes start time.

Yeah, absolutely. If your major goal is to simplify script writing this
is definitive a good option. I just wanted to point out that the
convenience comes at a price. :)
One possibility would be to write a script which attempts to automatically
generate these autoload statements, but store them statically in a single
file. The main reason I don't like that is, you've now added a "compile" step
to a script. It might work as an option, maybe a "development" vs "production"
mode.

Yeah, ugly.
Another possibility is to override const_missing, but that gets complex fast,
as Rails shows.

Also, keep in mind that the directory IO is shallow. That is, if you tell it
to autoload foo, it won't touch anything in foo/bar. If you create a file
bar.rb which requires autoload, it will look at foo/bar, but only once Bar is
autoloaded.

Thanks for the feedback!

You're welcome! Thanks for taking the time to digest it.

Kind regards

robert
 
D

David Masover

Yeah, absolutely. If your major goal is to simplify script writing this
is definitive a good option. I just wanted to point out that the
convenience comes at a price. :)

Well, I want a sane balance. I want to optimize start time to where an app
starts in under a second, versus thirty seconds -- and I think I've done that
without much additional complexity.

In other words, I think it's the best of both worlds.

If I _only_ wanted to simplify script writing, Ramaze has a much simpler
solution -- they've defined Kernel#acquire, which requires every .rb file in a
given directory tree. That's easier to write and easier to use, but as an app
gets bigger, it would get slower.
 
M

Marcin Raczkowski

I know about some work on merb, it collects depenedencies, then tries to
load them in diffirent order, and sees which one ends properly, AFAIK
there's no way to define alternative dependencies
 
R

Robert Klemme

Well, I want a sane balance.

Fair enough.
I want to optimize start time to where an app
starts in under a second, versus thirty seconds -- and I think I've done that
without much additional complexity.

Well, that sounds like a successful optimization operation. :)
In other words, I think it's the best of both worlds.

If I _only_ wanted to simplify script writing, Ramaze has a much simpler
solution -- they've defined Kernel#acquire, which requires every .rb file in a
given directory tree. That's easier to write and easier to use, but as an app
gets bigger, it would get slower.

Good pointer! Thanks for sharing.

Cheers

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top