confusing about autoload_paths vs eager_load_paths in rails 4
Asked Answered
G

2

67

I read a post about the rails load_paths, here is the link.

But, I am still confused about the difference between the autoload_paths and eager_load_paths:

I have tested them in a newly created Rails 4 project. It seems that they run the same way, that auto-reload in the development mode but in the production mode.

Gonidium answered 4/11, 2013 at 17:18 Comment(0)
I
218

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.

Ic answered 8/11, 2013 at 6:24 Comment(11)
Very detailed! ;) It's worth to mention that if you add a path to eager_load_paths then in developement env it acts like autoload_path (loaded on demand). So there is no point to add paths to autoload_paths at all. (Rails 4.1.0)Puncture
@Puncture Thanks for the mention, I've tried Rails 4.0.0 and 4.1.6, both works.Badgett
Thanks for the great detailed explanation. And for this part, "autoload_paths behaves differently in production between Rails 3 and 4", I've tried, but no work. And I haven't found any doc on it, could you tell me where to find or how to test correctly? Thanks. (I've added config.eager_load_paths += %W(#{config.root}/lib/tools) to application.rb, and touched foo.rb under tools dir, echo puts 'loading...'; class Foo; end in foo.rb, and rails c, rails c p to check)Badgett
Thanks for the explanation but after some investigation it seems that autoload_paths are not eager loaded in production. (Rails 4.1.7) But the opposite is true, paths in eager_load_paths are added to the load path and autoloaded in development.Canaday
@hakunin - @BigBourin's correct that autoload_paths does NOT eager load in production. See hereEmikoemil
There was definitely an issue filed, I believe it was this one: github.com/rails/rails/issues/6850 that made me believe in Rails 4 they fixed this. fxn comment says "Autoloading is not threadsafe, therefore any code that the user wanted to auto load should be eager loaded, because he has put no requires for it." and I kind of took it for their direction. Surprised that they didn't do that. /cc @BigBourinIc
@hakunin you may want to edit your answer then, as without reading these supplemental comments, one might be led to believe this is indeed true (re: auto-eager-loading everything in /app in production)Ethmoid
Is it true that everything under app/* is eagerly loaded? Because I have an active question where our production server isn't finding classes in app/lib, which seems to me should fall under this app/* pattern. Is there any way to verify what paths Rails is actually using once it's running? I already noticed that the console seems to find my class, even in production mode... :/Ledbetter
It's amazing how many times eager_load_paths gets mentioned in various articles without ever once mentioning what file this is in?Spelter
@Trejkaz you can verify which files are in eager_load_path with: Rails.application.config.eager_load_pathsStyrene
Is this statement still correct 7 years later? "It's important to note that eager_load_paths are not active in development environment" As far as I can tell, nowadays eager_load_paths will be considered for auto loading as well (so you just need to specify eager load). Probably already since 2014: blog.arkency.com/2014/11/…Enigmatic
N
14

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.

Neuroma answered 4/11, 2013 at 17:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.