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:
parent
c44d702a08
commit
549db9cc19
2 changed files with 47 additions and 9 deletions
|
@ -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
|
||||
---------------
|
||||
|
||||
|
|
|
@ -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`
|
||||
|
|
Loading…
Reference in a new issue