You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: guides/source/autoloading_and_reloading_constants.md
+44-45Lines changed: 44 additions & 45 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -69,7 +69,7 @@ Please, check the [Zeitwerk documentation](https://github.com/fxn/zeitwerk#file-
69
69
config.autoload_paths
70
70
---------------------
71
71
72
-
We refer to the list of application directories whose contents are to be autoloaded as _autoload paths_. For example, `app/models`. Such directories represent the root namespace: `Object`.
72
+
We refer to the list of application directories whose contents are to be autoloaded and (optionally) reloaded as _autoload paths_. For example, `app/models`. Such directories represent the root namespace: `Object`.
73
73
74
74
INFO. Autoload paths are called _root directories_ in Zeitwerk documentation, but we'll stay with "autoload path" in this guide.
Autoload paths automatically pick up any custom directories under `app`. For example, if your application has `app/presenters`, or `app/services`, etc., they are added to autoload paths.
87
+
Rails adds custom directories under `app` to the autoload paths automatically. For example, if your application has `app/presenters`, you don't need to configure anything in order to autoload presenters, it works out of the box.
88
88
89
-
The array of autoload paths can be extended by pushing to `config.autoload_paths`, in `config/application.rb` or `config/environments/*.rb`.
89
+
The array of default autoload paths can be extended by pushing to `config.autoload_paths`, in `config/application.rb` or `config/environments/*.rb`. For example:
90
+
91
+
```ruby
92
+
moduleMyApplication
93
+
classApplication < Rails::Application
94
+
config.autoload_paths <<"#{root}/extras"
95
+
end
96
+
end
97
+
```
98
+
99
+
Also, engines can push in body of the engine class and in their own `config/environments/*.rb`.
90
100
91
101
WARNING. Please do not mutate `ActiveSupport::Dependencies.autoload_paths`; the public interface to change autoload paths is `config.autoload_paths`.
92
102
93
-
These paths are managed by the `Rails.autoloaders.main` autoloader.
103
+
WARNING: You cannot autoload code in the autoload paths while the application boots. It particular, directly in `config/initializers/*.rb`. Please check [_Autoloading when the application boots_](#autoloading-when-the-application-boots) down below for valid ways to do that.
94
104
95
-
WARNING: The classes and modules defined in the autoload paths are reloadable. Therefore, you cannot autoload them in initializers. Please check [_Autoloading when the application boots_](#autoloading-when-the-application-boots) down below for valid ways to do that.
105
+
The autoload paths are managed by the `Rails.autoloaders.main` autoloader.
96
106
97
107
config.autoload_once_paths
98
108
--------------------------
99
109
100
-
Occasionally, you may want to be able to autoload classes and modules without reloading them. This is key for classes and modules that are cached somewhere.
110
+
You may want to be able to autoload classes and modules without reloading them. The autoload once paths store code that can be autoloaded, but won't be reloaded.
111
+
112
+
By default, this collection is empty, but you can extend it pushing to `config.autoload_once_paths`. You can do so in `config/application.rb` or `config/environments/*.rb`. For example:
Also, engines can push in body of the engine class and in their own `config/environments/*.rb`.
123
+
124
+
INFO. If `app/serializers` is pushed to `config.autoload_once_paths`, Rails no longer considers this an autoload path, despite being a custom directory under `app`. This setting overrides that rule.
125
+
126
+
This is key for classes and modules that are cached in places that survive reloads, like the Rails framework itself.
101
127
102
128
For example, Active Job serializers are stored inside Active Job:
103
129
@@ -106,6 +132,8 @@ For example, Active Job serializers are stored inside Active Job:
and Active Job itself is not reloaded when there's a reload, only application and engines code in the autoload paths is.
136
+
109
137
Making `MoneySerializer` reloadable would be confusing, because reloading an edited version would have no effect on that class object stored in Active Job. Indeed, if `MoneySerializer` was reloadable, starting with Rails 7 such initializer would raise a `NameError`.
110
138
111
139
Another use case are engines decorating framework classes:
@@ -120,26 +148,16 @@ end
120
148
121
149
There, the module object stored in `MyDecoration` by the time the initializer runs becomes an ancestor of `ActionController::Base`, and reloading `MyDecoration` is pointless, it won't affect that ancestor chain.
122
150
123
-
The directories in `config.autoload_once_paths` are managed by `Rails.autoloaders.once` and cover those use cases by allowing you to autoload classes and modules that won't be reloaded.
124
-
125
-
The array of autoload once paths can be extended by pushing to `config.autoload_once_paths`, in `config/application.rb` or `config/environments/*.rb`. For example:
INFO: Technically, you can autoload classes and modules managed by the `once` autoloader in any initializer that runs after `:bootstrap_hook`.
158
+
INFO: Technically, you can autoload classes and modules managed by the `once` autoloader in any initializer that runs after `:bootstrap_hook`.
159
+
160
+
The autoload once paths are managed by `Rails.autoloaders.once`.
143
161
144
162
$LOAD_PATH
145
163
----------
@@ -156,7 +174,7 @@ That may speed up legitimate `require` calls a bit since there are fewer lookups
156
174
Reloading
157
175
---------
158
176
159
-
Rails automatically reloads classes and modules if application files change.
177
+
Rails automatically reloads classes and modules if application files in the autoload paths change.
160
178
161
179
More precisely, if the web server is running and application files have been modified, Rails unloads all autoloaded constants just before the next request is processed. That way, application classes or modules used during that request will be autoloaded again, thus picking up their current implementation in the file system.
162
180
@@ -184,26 +202,7 @@ As you can see, the class object stored in the `User` constant is different afte
184
202
185
203
It is very important to understand that Ruby does not have a way to truly reload classes and modules in memory, and have that reflected everywhere they are already used. Technically, "unloading" the `User` class means removing the `User` constant via `Object.send(:remove_const, "User")`.
186
204
187
-
Therefore, code that references a reloadable class or module, but that is not executed again on reload, becomes stale. Let's see an example next.
The idea would be to use `$PAYMENT_GATEWAY` in the code, and let the initializer set that to the actual implementation depending on the environment.
199
-
200
-
On reload, `MockedGateway` is reloaded, but `$PAYMENT_GATEWAY` is not updated because initializers only run on boot. Therefore, it won't reflect the changes.
201
-
202
-
There are several ways to do this safely. For instance, the application could define a class method `PaymentGateway.impl` whose definition depends on the environment; or could define `PaymentGateway` to have a parent class or mixin that depends on the environment; or use the same global variable trick, but in a reloader callback, as explained below.
203
-
204
-
Let's see other situations that involve stale class or module objects.
205
-
206
-
Check out this Rails console session:
205
+
For example, check out this Rails console session:
207
206
208
207
```irb
209
208
irb> joe = User.new
@@ -232,8 +231,8 @@ Bottom line: **do not cache reloadable classes or modules**.
232
231
Applications can safely autoload constants during boot using a reloader callback:
To have changes in that middleware reflected, you need to restart the server.
255
254
255
+
Another possibility is to autoload from the autoload once paths. Please check the section [`config.autoload_once_paths`](#config-autoload-once-paths) above.
256
+
256
257
257
258
Eager Loading
258
259
-------------
@@ -451,12 +452,10 @@ Rails.autoloaders.main
451
452
Rails.autoloaders.once
452
453
```
453
454
454
-
The former is the main one. The latter is there mostly for backwards compatibility reasons, in case the application has something in `config.autoload_once_paths` (this is discouraged nowadays).
455
-
456
455
The predicate
457
456
458
457
```ruby
459
458
Rails.autoloaders.zeitwerk_enabled?
460
459
```
461
460
462
-
is still available in Rails 7 applications, for compatibility with engines may want to support Rails 6.x. It just returns `true`.
461
+
is still available in Rails 7 applications, and returns `true`.
0 commit comments