1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Document autoloading and engines [skip ci]

This commit is contained in:
Xavier Noria 2021-08-04 23:41:01 +02:00
parent c44d702a08
commit 549db9cc19
2 changed files with 47 additions and 9 deletions

View file

@ -348,6 +348,37 @@ There is no global configuration that can affect said instances; they are determ
You can even define a custom inflector for full flexibility. Please check the [Zeitwerk documentation](https://github.com/fxn/zeitwerk#custom-inflector) for further details.
Autoloading and Engines
-----------------------
Engines run in the context of a parent application, and their code is autoloaded, reloaded, and eager loaded by the parent application. If the application runs in `zeitwerk` mode, the engine code is loaded by `zeitwerk` mode. If the application runs in `classic` mode, the engine code is loaded by `classic` mode.
When Rails boots, engine directories are added to the autoload paths, and from the point of view of the autoloader, there's no difference. Autoloaders' main input are the autoload paths, and whether they belong to the application source tree or to some engine source tree is irrelevant.
For example, this application uses [Devise](https://github.com/heartcombo/devise):
```
% bin/rails runner 'pp ActiveSupport::Dependencies.autoload_paths'
[".../app/controllers",
".../app/controllers/concerns",
".../app/helpers",
".../app/models",
".../app/models/concerns",
".../gems/devise-4.8.0/app/controllers",
".../gems/devise-4.8.0/app/helpers",
".../gems/devise-4.8.0/app/mailers"]
```
If the engine controls the autoloading mode of its parent application, the engine can be written as usual.
However, if an engine supports Rails 6 or Rails 6.1 and does not control its parent applications, it has to be ready to run under either `classic` or `zeitwerk` mode. Things to take into account:
1. If `classic` mode would need a `require_dependency` call to ensure some constant is loaded at some point, write it. While `zeitwerk` would not need it, it won't hurt, will just work in `zeitwerk` mode too.
2. `classic` mode underscores constant names ("User" -> "user.rb"), and `zeitwerk` mode camelizes file names ("user.rb" -> "User"). They coincide in most cases, but they don't if there are series of consecutive uppercase letters as in "HTMLParser". The easiest way to be compatible is to avoid such names: "HtmlParser".
3. In `classic` mode, a file `app/model/concerns/foo.rb` is allowed to define both `Foo` and `Concerns::Foo`. In `zeitwerk` mode, there's only one option: it has to define `Foo`. In order to be compatible, define `Foo`.
Troubleshooting
---------------

View file

@ -238,14 +238,15 @@ NOTE: The `ApplicationController` class inside an engine is named just like a
Rails application in order to make it easier for you to convert your
applications into engines.
NOTE: Because of the way that Ruby does constant lookup you may run into a situation
where your engine controller is inheriting from the main application controller and
not your engine's application controller. Ruby is able to resolve the `ApplicationController` constant, and therefore the autoloading mechanism is not triggered. See the section [When Constants Aren't Missed](autoloading_and_reloading_constants_classic_mode.html#when-constants-aren-t-missed).
The best way to prevent this from happening is to use `require_dependency` to ensure that the engine's application
controller is loaded. For example:
NOTE: If the parent application runs in `classic` mode, you may run into a
situation where your engine controller is inheriting from the main application
controller and not your engine's application controller. The best way to prevent
this is to switch to `zeitwerk` mode in the parent application. Otherwise, use
`require_dependency` to ensure that the engine's application controller is
loaded. For example:
```ruby
# app/controllers/blorgh/articles_controller.rb:
# ONLY NEEDED IN `classic` MODE.
require_dependency "blorgh/application_controller"
module Blorgh
@ -255,9 +256,9 @@ module Blorgh
end
```
WARNING: Don't use `require` because it will break the automatic reloading of classes
in the development environment - using `require_dependency` ensures that classes are
loaded and unloaded in the correct manner.
WARNING: Don't use `require` because it will break the automatic reloading of
classes in the development environment - using `require_dependency` ensures that
classes are loaded and unloaded in the correct manner.
Just like for `app/controllers`, you will find a `blorgh` subdirectory under
the `app/helpers`, `app/jobs`, `app/mailers` and `app/models` directories
@ -1227,6 +1228,12 @@ module Blorgh::Concerns::Models::Article
end
```
### Autoloading and Engines
Please check the [Autoloading and Reloading Constants](autoloading_and_reloading_constants.html#autoloading-and-engines)
guide for more information about autoloading and engines.
### Overriding Views
When Rails looks for a view to render, it will first look in the `app/views`