# Kernel#autoload vs require\_relative

**URL:** <https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367>\
**Category:** Ruby\
**Created:** [June 16, 2011, 1:30pm UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367 "2011-06-16T13:30:17Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [June 16, 2011, 1:30pm UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367/1 "2011-06-16T13:30:17Z")

</div>

I understand that for require to work relative to the given **FILE** ’s  
directory one needs to either $LOAD\_PATH \<\< File.dirname( **FILE** ) or  
use require\_relative (with the latter being preferred, I presume).

Is there such an alternative for Kernel#autoload  
– and if not, should there be one?

I’m thinking about lib/foo.rb containing

module Foo  
autoload :Bar, ‘foo/bar.rb’  
autoload :Baz, ‘foo/baz.rb’  
autoload :Qux, ‘foo/qux.rb’  
end

(which doesn’t work without $LOAD\_PATH munging), as  
opposed to the (currently working) lib/foo.rb with

require\_relative ‘foo/bar.rb’  
require\_relative ‘foo/baz.rb’  
require\_relative ‘foo/qux.rb’

— Piotr S.

---

<div class="post-metadata">

**Author:** ![piotrs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ee59a6/32.png) [@piotrs](https://www.ruby-forum.com/u/piotrs)\
**Post date:** [June 16, 2011, 5:55pm UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367/2 "2011-06-16T17:55:00Z")

</div>

On Jun 16, 2011, at 04:29 , Piotr S. wrote:

> autoload :Bar, ‘foo/bar.rb’  
> autoload :Baz, ‘foo/baz.rb’  
> autoload :Qux, ‘foo/qux.rb’  
> end
> 
> (which doesnt work without $LOAD\_PATH munging),

I wouldn’t call having ‘lib’ in your LOAD\_PATH as munging. I’d call that  
business as usual. Rubygems supports that as a default. All the usual  
rake tasks and test tools support that as a default. It just seems sane  
to me… Much more sane than File.dirname( **FILE** ) does or  
require\_relative.

(btw, you don’t need the “.rb” part–that’s just ugly)

> as  
> opposed to the (currently working) lib/foo.rb with
> 
> require\_relative ‘foo/bar.rb’  
> require\_relative ‘foo/baz.rb’  
> require\_relative ‘foo/qux.rb’

again, “.rb” not needed.

---

<div class="post-metadata">

**Author:** ![piotrs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ee59a6/32.png) [@piotrs](https://www.ruby-forum.com/u/piotrs)\
**Post date:** [June 16, 2011, 6:28pm UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367/3 "2011-06-16T18:28:19Z")

</div>

On Jun 16, 7:29am, Piotr S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> autoload :Bar, ‘foo/bar.rb’  
> autoload :Baz, ‘foo/baz.rb’  
> autoload :Qux, ‘foo/qux.rb’  
> end
> 
> (which doesnt work without $LOAD\_PATH munging), as  
> opposed to the (currently working) lib/foo.rb with
> 
> require\_relative ‘foo/bar.rb’  
> require\_relative ‘foo/baz.rb’  
> require\_relative ‘foo/qux.rb’

The question is, are these libs going to loaded anyway regardless of  
what is done with the library? If so than you should just go ahead and  
load the libs right away with require\_relative. Moreover,  
require\_relative doesn’t have to search though all the load paths, so  
it will speed up load times. autoload is only useful for a class or  
module that is frequently not used in any given run.

---

<div class="post-metadata">

**Author:** ![piotrs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ee59a6/32.png) [@piotrs](https://www.ruby-forum.com/u/piotrs)\
**Post date:** [June 16, 2011, 6:51pm UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367/4 "2011-06-16T18:51:44Z")

</div>

Ryan D.:

> On Jun 16, 2011, at 04:29 , Piotr S. wrote:

> > I understand that for require to work relative to the given **FILE** ’s  
> > directory one needs to either $LOAD\_PATH \<\< File.dirname( **FILE** ) or  
> > use require\_relative (with the latter being preferred, I presume).

> > Is there such an alternative for Kernel#autoload  
> > – and if not, should there be one?

> > I’m thinking about lib/foo.rb containing

> > module Foo  
> > autoload :Bar, ‘foo/bar’  
> > autoload :Baz, ‘foo/baz’  
> > autoload :Qux, ‘foo/qux’  
> > end

> > (which doesn’t work without $LOAD\_PATH munging),

> I wouldn’t call having ‘lib’ in your LOAD\_PATH as munging.

Ok (and I understand your arguments).

> It just seems sane to me… Much more sane than  
> File.dirname( **FILE** ) does or require\_relative.

Hm, I do prefer using require\_relative over require + $LOAD\_PATH  
changes; it looks cleaner to me and doesn’t touch shared  
globals, but I guess that’s more of a personal preference.

What I was trying to ask is whether there couldn’t be  
a Kernel#autoload\_relative call or a ‘relative: true’  
optional parameter to Kernel#autoload to make it symmetric  
with the require/require\_relative combination. I understand  
your answer would be ‘there’s no need’. 🙂

> (btw, you don’t need the “.rb” part–that’s just ugly)

Fully agreed; fixed in the quotation above  
(I shouldn’t post before my morning coffee).

— Piotr S.

---

<div class="post-metadata">

**Author:** ![piotrs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ee59a6/32.png) [@piotrs](https://www.ruby-forum.com/u/piotrs)\
**Post date:** [June 16, 2011, 6:58pm UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367/5 "2011-06-16T18:58:31Z")

</div>

Intransition:

> On Jun 16, 7:29 am, Piotr S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > $LOAD\_PATH \<\< File.dirname( **FILE** )  
> > module Foo  
> > autoload :Bar, ‘foo/bar’  
> > autoload :Baz, ‘foo/baz’  
> > autoload :Qux, ‘foo/qux’  
> > end

> > require\_relative ‘foo/bar’  
> > require\_relative ‘foo/baz’  
> > require\_relative ‘foo/qux’

> The question is, are these libs going to loaded  
> anyway regardless of what is done with the library?

In my case it depends on the library in question; I was  
looking for an approach that could use a relative-path  
Kernel#autoload without touching $LOAD\_PATH.

— Piotr S.

---

<div class="post-metadata">

**Author:** ![piotrs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ee59a6/32.png) [@piotrs](https://www.ruby-forum.com/u/piotrs)\
**Post date:** [June 16, 2011, 7:12pm UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367/6 "2011-06-16T19:12:43Z")

</div>

Piotr S.:

> Hm, I do prefer using require\_relative over require + $LOAD\_PATH  
> changes; it looks cleaner to me and doesn’t touch shared  
> globals, but I guess that’s more of a personal preference.

…and now I recalled my particular use-case:

require\_relative ‘set’

will pull in ‘my’ Set, whereas

require ‘set’

will pull in either ‘my’ Set or the stdlib’s Set depending on whether  
I prepended or appended the $LOAD\_PATH with File.dirname( **FILE** ).

// I do agree name clashes are at best avoided and at worst  
// thoroughly documented, with require ‘./set’ being a (somewhat  
// ugly) solution as well, but require\_relative’s independence  
// from $LOAD\_PATH ordering does look appealing to me, hence my  
// longing for Kernel#autoload\_relative. 🙂

— Piotr S.

---

<div class="post-metadata">

**Author:** ![piotrs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ee59a6/32.png) [@piotrs](https://www.ruby-forum.com/u/piotrs)\
**Post date:** [June 16, 2011, 10:18pm UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367/7 "2011-06-16T22:18:36Z")

</div>

On Jun 16, 2011, at 10:07 , Piotr S. wrote:

> will pull in my Set, whereas
> 
> require ‘set’
> 
> will pull in either my Set or the stdlibs Set depending on whether  
> I prepended or appended the $LOAD\_PATH with File.dirname( **FILE** ).

I know you know this but it needs to be said for others:

require ‘my/set’

---

<div class="post-metadata">

**Author:** ![piotrs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ee59a6/32.png) [@piotrs](https://www.ruby-forum.com/u/piotrs)\
**Post date:** [June 16, 2011, 7:32pm UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367/8 "2011-06-16T19:32:27Z")

</div>

> Hm, I do prefer using require\_relative over require + $LOAD\_PATH

changes; it looks cleaner to me and doesnt touch shared

globals, but I guess thats more of a personal preference.

It’s also more secure, which is why . was removed in the first place. 🙂

---

<div class="post-metadata">

**Author:** ![piotrs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ee59a6/32.png) [@piotrs](https://www.ruby-forum.com/u/piotrs)\
**Post date:** [June 17, 2011, 9:34am UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367/9 "2011-06-17T09:34:04Z")

</div>

On Thursday, June 16, 2011 11:50:57 AM Piotr S. wrote:

> Hm, I do prefer using require\_relative over require + $LOAD\_PATH  
> changes; it looks cleaner to me and doesn’t touch shared  
> globals, but I guess that’s more of a personal preference.

So, while writing the rest of this (long) post, I think I actually dug  
up a  
solution for you, in the form of the ‘autoloader’ gem I wrote awhile  
back:

> **[GitHub - masover/autoloader: Crawl a directory at a time, adding files via...](https://github.com/masover/autoloader)**
>
> Crawl a directory at a time, adding files via Kernel#autoload

If everything in your ‘lib’ hierarchy is normally loaded via autoload,  
and  
follows a decent naming convention, I think this solves your problem. In  
your  
example, somewhere in ‘lib/foo.rb’, you could do this:

require ‘autoloader’  
AutoLoader \<\< File.dirname( **FILE** )

module Foo  
include AutoLoader  
end

Ok, there’s some **FILE** ugliness, but in exchange, you automagically  
get  
‘autoload’ statements generated for everything, and you don’t have to  
modify  
your load path.

Caveat: I wrote this awhile ago, when Merb was still a thing. It seems  
to  
still work, but you might still want to read it to understand what it  
does.  
It’s not that long:

> <https://github.com/masover/autoloader/blob/master/lib/autoloader.rb>

> What I was trying to ask is whether there couldn’t be  
> a Kernel#autoload\_relative call or a ‘relative: true’  
> optional parameter to Kernel#autoload to make it symmetric  
> with the require/require\_relative combination…

There is one thing I would _much_ rather have than this: Enough hooks  
into  
either the language or the autoload mechanism so that things like this  
are  
possible to do entirely inside Ruby.

That is: Currently, we have const\_missing, but it isn’t called when  
someone  
tries to define a constant. For example, if I have Rails-style  
const\_missing  
hacks, and I want to re-open a previously-defined module, I need to do  
this:

Foo::Bar.module\_eval do  
…  
end

instead of:

module Foo  
module Bar  
…  
end  
end

The latter will never hit const\_missing, and would thus never load  
foo.rb or  
whatever. And sure, if I’m re-opening Bar, I’m probably better off  
defining a  
separate module and forcing Bar to include it. But what if this is  
inside  
foo/bar.rb? Now if I say

require ‘foo/bar’

I’ll get Foo::Bar, but I won’t ever load foo.rb – whereas, say,

Foo.module\_eval do  
module Bar  
…  
end  
end

…ew.

Anyway, what I really want is something like:

autoload :Foo do  
# block to ensure Foo is defined  
end

In this case, autoload is the wrong word, but this would let me write  
the  
ultimate autoload-based replacement for the old Rails const\_missing  
hack. What  
I have now is in the ‘autoloader’ gem:

AutoLoader \<\< ‘/path/to/lib’

It will crawl ‘lib’ one level deep, take every ‘.rb’ file, and create an  
‘autoload’ tag for it. But in order to map Foo::Bar to ‘foo/bar.rb’, I  
still  
need the user to have a foo.rb file which does some extra work:

module Foo  
include AutoLoader  
end

I can’t think of any way to make this work other than having some  
callback  
fire when the file actually gets loaded. Last I checked, Kernel#autoload  
would  
call ‘require’ from C when fired, so overloading ‘require’ doesn’t help.  
And  
const\_missing isn’t a substitute, nor is there any way to duplicate  
Kernel#autoload’s functionality from Ruby.

I actually think autoloading via require\_relative is a bad idea, versus  
just  
adding something to the load path. Some people think autoload itself is  
a bad  
idea. There are probably workarounds enough for both of us. But it does  
frustrate me that Kernel#autoload is so inflexible, and it really  
doesn’t seem  
like it needs to be.

---

<div class="post-metadata">

**Author:** ![piotrs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ee59a6/32.png) [@piotrs](https://www.ruby-forum.com/u/piotrs)\
**Post date:** [June 17, 2011, 1:07pm UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367/10 "2011-06-17T13:07:16Z")

</div>

On Fri, Jun 17, 2011 at 9:33 AM, David M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> If everything in your ‘lib’ hierarchy is normally loaded via autoload, and  
> Ok, there’s some **FILE** ugliness, but in exchange, you automagically get  
> ‘autoload’ statements generated for everything, and you don’t have to modify  
> your load path.

I think there is a cure for that:

module AutoLoader  
def self.included(cl)  
# “alc.rb:33:in `class:X’”  
file = caller[1][%r{\A(.\*?):\d+:in\s}, 1]  
self \<\< File.dirname(file)  
end

# debug:

def self.\<\<(d)  
puts “Adding directory: #{d}”  
end  
end

> AutoLoader \<\< ‘/path/to/lib’
> 
> It will crawl ‘lib’ one level deep, take every ‘.rb’ file, and create an  
> ‘autoload’ tag for it. But in order to map Foo::Bar to ‘foo/bar.rb’, I still  
> need the user to have a foo.rb file which does some extra work:
> 
> module Foo  
> include AutoLoader  
> end

In Ruby land we could at least do

auto\_module :Foo do

# no more “include” needed here

end

or even

auto\_module :Foo

if there is nothing that needs to be defined here. But then we have a  
“require” statement and a file with a single line - that doesn’t feel  
right.

> like it needs to be.  
> Hm, for me this generally works pretty well: I have a lib directory  
> which is part of the load path and for larger libraries I have an  
> initial file (e.g. “foo.rb”) where the root namespace is defined  
> together with a set of autoload directives which then load files like  
> “foo/class1”, “foo/class2” etc.

Basically, as long as there is no fixed relationship between file name  
and content, there will always be a level of manual intervention  
needed. True, you can have conventions manifest in code (like your  
AutoLoader) but as long as there is no predominant convention that  
fits all needs we won’t have a generalized solution. The advantage of  
the current autoload approach is that it makes things explicit.  
Downside is still that the relativity issue (with regard to pathnames,  
not E=mc2) is still there.

But that can be solved with

class Module  
def autoload\_r(const, path)  
file = caller[1][%r{\A(.\*?):\d+:in\s}, 1]  
autoload(const, File.join(File.dirname(file), path))  
end  
end

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![piotrs](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ee59a6/32.png) [@piotrs](https://www.ruby-forum.com/u/piotrs)\
**Post date:** [June 18, 2011, 12:18am UTC](https://www.ruby-forum.com/t/kernel-autoload-vs-require-relative/208367/11 "2011-06-18T00:18:29Z")

</div>

On Friday, June 17, 2011 06:06:33 AM Robert K. wrote:

> > to modify your load path.
> 
> # debug:
> 
> def self.\<\<(d)  
> puts “Adding directory: #{d}”  
> end  
> end

That needs some work. Dirname isn’t enough, since right now, things may  
be  
nested arbitrarily deep – I could have lib/foo/bar.rb which looks  
similar:

module Foo  
module Bar  
include AutoLoader  
end  
end

But I clearly still want ‘lib’ to be the top-level directory for this  
magic.  
That is, I want foo/bar/baz.rb to map to Foo::Bar::Baz, not to Bar::Baz.

I really don’t mind the **FILE** ugliness, given that it only has to  
happen  
once, at the very top of the project. The assumption is that you’d never  
have  
a reason to require anything other than this top-level library, since  
everything else is included with autoload, so you’ll only get the stuff  
you  
need – that is, there’s no advantage to:

require ‘foo/bar’  
Foo::Bar.do\_something!

rather than

require ‘foo’  
Foo::Bar.do\_something!

So I have no motivation to get rid of **FILE** , though maybe there  
should be  
some convenience version, maybe something like:

AutoLoader.add\_relative\_path ‘path/to/lib’ # defaults to ‘.’

> if there is nothing that needs to be defined here. But then we have a  
> “require” statement and a file with a single line - that doesn’t feel  
> right.

Yeah, it doesn’t really solve the problem. ‘include’ isn’t the problem.  
The  
problem is that this library shouldn’t force me to add _any_ special  
syntax or  
calls, let alone special files, to make it work. It should just let me  
pretend  
that my entire directory got slurped – this was inspired by Rails’  
const\_missing behavior, but also by Ramaze’s “acquire” which just  
requires  
every ruby file in a given path.

> Hm, for me this generally works pretty well: I have a lib directory  
> which is part of the load path and for larger libraries I have an  
> initial file (e.g. “foo.rb”) where the root namespace is defined  
> together with a set of autoload directives which then load files like  
> “foo/class1”, “foo/class2” etc.

I don’t mind this, except for two things:

- I shouldn’t have to modify the load path. I should be doing it  
anyway,  
maybe, but it shouldn’t be a requirement.

- It’s annoying having to explicitly autoload everything, especially  
when I’m  
usually following a convention.

> Basically, as long as there is no fixed relationship between file name  
> and content, there will always be a level of manual intervention  
> needed.

I like convention over configuration. Not convention instead of  
configuration  
– there’s always manual autoload if I need them, and I suspect the  
first  
thing I’d change about AutoLoader at this point is being able to specify  
which  
files are included and which aren’t. But when 99% of the time, the  
process is:

- Create foo/bar.rb.
  - Create class Foo::Bar in foo/bar.rb.
  - Add autoload line to foo.rb.

- Did I really want it called bar.rb? Maybe baz.rb is a better name.
  - git mv foo/bar.rb foo/baz.rb
  - Change Foo::Bar to Foo::Baz in foo/baz.rb
  - Change autoload line in foo.rb.
  - Update any other references.

- Maybe I want to split it into foo/one.rb and foo/two.rb.
  - create foo/one.rb, foo/two.rb.
  - edit/move some stuff, update references.
  - git add foo/one.rb foo/two.rb
  - git rm foo/baz.rb
  - edit foo.rb and update the autoload line.

This is annoying. Sure, it’s going to be annoying no matter what, but  
anything  
I can do to ease this pain is helpful, because I do this kind of thing a  
_lot_  
in the first few hours of a project. Anytime I see a better  
organization,  
_now_ is the time, before I’ve published it to a dev team (let alone to  
the  
world via Github) and locked myself into an API.

It’s also annoyingly redundant and menial. This is something the machine  
can  
do perfectly well for me, so why not let it?

Also worth mentioning: When you’re autoloading everything, anything  
beyond the  
top-level “require ‘yourgem’” is no longer part of your public API. So,  
any  
naming convention is entirely for your own convenience at this point. I  
just  
did what Rails did and made it convenient to follow that one naming  
convention. So when I actually use AutoLoader, I don’t have exceptions  
to that  
naming convention, or, really, any reason to.

> The advantage of  
> the current autoload approach is that it makes things explicit.  
> Downside is still that the relativity issue (with regard to pathnames,  
> not E=mc2) is still there.

Well, as you demonstrate, that’s easily solved. But in my opinion, the  
other  
downside is that it makes things explicit, when there isn’t a good  
reason for  
them to be.

At this point, AutoLoader isn’t about solving the relativity issue, it’s  
about  
DRYing things up a bit.
