confusing about autoload_paths vs eager_load_paths in rails 4
Author of the linked article here. Here's an attempt to clear up the confusion, going off of @fkreusch's answer.
In Ruby you have to require every .rb
file in order to have its code run. However, notice how in Rails you never specifically require any of your models, controllers, or other files in the app/
dir. Why is that? That's because in Rails app/*
is in autoload_paths
. This means that when you run your rails app in development (for example via rails console
) — none of the models and controllers are actually required by ruby yet. Rails uses special magical feature of ruby to actually wait until the code mentions a constant, say Book
, and only then it would run require 'book'
which it finds in one of the autoload_paths
. This gives you faster console and server startup in development, because nothing gets required when you start it, only when code actually needs it.
Now, this behavior is good for local development, but what about production? Imagine that in production your server does the same type of magical constant loading (autoloading). It's not the end of the world really, you start your server in production, and people start browsing your pages slightly slower, because some of the files will need to be autoloaded. Yes, it's slower for those few initial requests, while the server "warms up", but it's not that bad. Except, that's not the end of the story.
If you are running on ruby 1.9.x (if I recall correctly), then auto-requiring files like that is not thread safe. So if you are using a server like puma, you will run into problems. Even if you aren't using a multi-threaded server, you are still probably better off having your whole application get required "proactively", on startup. This means that in production, you want every model, every controller, etc all fully required as you start your app, and you don't mind the longer startup time. This is called eager loading. All ruby files get eagerly loaded, get it? But how can you do that, if your rails app doesn't have a single require
statement? That's where eager_load_paths
come in. Whatever you put in them, all the files in all the directories underneath those paths will be required at startup in production. Hope this clears it up.
It's important to note that eager_load_paths
are not active in development environment, so whatever you put in them will not be eagerly required immediately in development, only in production.
It's also important to note that just putting something into autoload_paths
will not make it eager-loaded in production. Unfortunately. You have to explicitly put it into eager_load_paths
as well.
Another interesting quirk is that in every rails app, all directories under app/
are automatically in both autoload_paths
and eager_load_paths
, meaning that adding a directory there requires no further actions.
Basically, autoload_paths
are paths Rails will use to try loading your classes automatically. E.g. when you call Book
, if that class isn't loaded yet, it will go through the autoload_paths
and look for it in those paths.
In production, it might be better to load those upfront to avoid autoload concurrent issues. For that, it provides the eager_load_paths
. Paths in that list will be required upfront when your application starts.