Configurable autoloaders?

I see that Rails::Autoloaders introduces two loaders:

  • main
  • once

As Rails apps grow in size, domains evolve, and with these, service boundaries are drawn. A couple common examples of this are side-affects of using GraphQL and Service Objects. The files tied to these domains can grow quite large, and due to the nature of the new auto-loaders, necessitate some a-typical path resolution (e.g. app/services/services, revisiting lib, etc.). In addition, since there is no usage of constants outside of these domains, there are many contexts in which these files do not need to be loaded (thinking of jobs, tasks, etc.).

Since Rails is an opinionated framework, I’m curious of two things:

  • Are there plans to introduce a new common path for resolving domain-specific code segregation?
  • Are there plans to allow configuring additional auto-loaders?

I’m curious how others are resolving this now, and how it might be better.

The difference between the once and main autoloaders is that once does not reload and supports autoloading in initializers. On the other hand, main supports reloading.

However, you can spread what main manages in as many root directories as you want. It already manages engines in addition to the application itself.

Then, gem dependencies may be using their own autoloader.

Can you be more concrete about the kind of scenario where you find this insufficient?

First off, thank you @fxn for Zeitwerk! It is leaps and bounds better than The Before Times of Ruby Autoloading™.

I have two concerns with the new Rails auto-loading that have caused problems, and a bit against the grain solutions, in nearly every Rails app. I apologize for not giving more concrete examples :person_facepalming:

1. Namespacing root directories inside the app directory

This issue is quite common, and causes a lot of pain during migrations to Zeitwerk and adds some conceptual comprehension overhead.

I saw two separate issues where you gave some possible solutions:

  • This zeitwerk issue suggesting mutating Rails autoload_paths
  • This rails issue suggesting mutating eager_load_paths as well ass ignoring the directory with the main autoloader along the lines of Rails.autoloaders.main.ignore("app/custom").

The bottom-line suggestion I’ve seen repeated is to nest these directories “appropriately” in app/custom/custom if we want a root Custom namespace within the app directory.

It would be nice if there was either:

i. A Rails API to tie into that could standardize this common pattern

ii. An official Rails Way to organize these custom roots that would Just Work

2. Eager-loading above mentioned namespaces separately

Part of my interest in configuring additional auto-loaders (and maybe I’m thinking about this wrong), is a desire to isolate and optimize what gets eagerly-loaded. Consider the following scenarios:

a. Running a unit test on a specific file requires loading the entire application. Even with spring, load times can grow quite large depending on the context (e.g. working with many dependencies that can be reloaded).

b. Run a rake task that targets a very specific (and often known) set of constants and Rails features. Similar issues surface with needing to front-load the application.

My thinking here is that multiple (and configurable) auto-loaders could help isolate common scenarios like this.


I’m open to suggestions here.