aboutsummaryrefslogtreecommitdiffstats
path: root/guides
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2019-05-08 10:09:15 +0200
committerXavier Noria <fxn@hashref.com>2019-05-08 10:09:15 +0200
commit65bdd6ad085a02b976cd36f135c2a5ffb522e5a0 (patch)
tree70630f20df42e6180a93f7cbc9bf48210c52cac6 /guides
parentd155f61b64e7cecc56fe6281d084e1b12a0a3584 (diff)
downloadrails-65bdd6ad085a02b976cd36f135c2a5ffb522e5a0.tar.gz
rails-65bdd6ad085a02b976cd36f135c2a5ffb522e5a0.tar.bz2
rails-65bdd6ad085a02b976cd36f135c2a5ffb522e5a0.zip
documents autoloading in the upgrading guide [ci skip]
Diffstat (limited to 'guides')
-rw-r--r--guides/source/upgrading_ruby_on_rails.md172
1 files changed, 172 insertions, 0 deletions
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index 7e4152aa51..65274f0946 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -133,6 +133,178 @@ Action Cable JavaScript API:
+ ActionCable.logger.enabled = false
```
+### Autoloading
+
+The default configuration for Rails 6
+
+```ruby
+# config/application.rb
+
+load_defaults "6.0"
+```
+
+enables `zeitwerk` autoloading mode on CRuby. In that mode, autoloading, reloading, and eager loading are managed by [Zeitwerk](https://github.com/fxn/zeitwerk).
+
+#### Public API
+
+In general, applications do not need to use the API of Zeitwerk directly. Rails sets things up according to the existing contract: `config.autoload_paths`, `config.cache_classes`, etc.
+
+While applications should stick to that interface, the actual Zeitwerk loader object can be accessed as
+
+```ruby
+Rails.autoloaders.main
+```
+
+That may be handy if you need to preload STIs or configure a custom inflector, for example.
+
+#### Project Structure
+
+If the application being upgraded autoloads correctly, the project structure should be already mostly compatible.
+
+However, `classic` mode infers file names from missing constant names (`underscore`), whereas `zeitwerk` mode infers constant names from file names (`camelize`). These helpers are not always inverse of each other, in particular if acronyms are involved. For instance, `"FOO".underscore` is `"foo"`, but `"foo".camelize` is `"Foo"`, not `"FOO"`. Compatibility can be checked by setting `classic` mode first temporarily:
+
+```ruby
+# config/application.rb
+
+load_defaults "6.0"
+config.autoloader = :classic
+```
+
+and then running
+
+```
+bin/rails zeitwerk:check
+```
+
+When all is good, you can delete `config.autoloader = :classic`.
+
+#### require_dependency
+
+All known use cases of `require_dependency` have been eliminated, you should grep the project and delete them.
+
+In the case of STIs with a hierarchy of more than two levels, you can preload the leaves of the hierarchy in an initializer:
+
+```ruby
+# config/initializers/preload_stis.rb
+
+# By preloading leaves, the entire hierarchy is loaded upwards following
+# the references to superclasses in the class definitions.
+sti_leaves = %w(
+ app/models/leaf1.rb
+ app/models/leaf2.rb
+ app/models/leaf3.rb
+)
+Rails.autoloaders.main.preload(sti_leaves)
+```
+
+#### Qualified names in class and module definitions
+
+You can now robustly use constant paths in class and module definitions:
+
+```ruby
+# Autoloading in this class' body matches Ruby semantics now.
+class Admin::UsersController < ApplicationController
+ # ...
+end
+```
+
+A gotcha to be aware of is that, depending on the order of execution, the classic autoloader could sometimes be able to autoload `Foo::Wadus` in
+
+```ruby
+class Foo::Bar
+ Wadus
+end
+```
+
+That does not match Ruby semantics because `Foo` is not in the nesting, and won't work at all in `zeitwerk` mode. If you find such corner case you can use the qualified name `Foo::Wadus`:
+
+```ruby
+class Foo::Bar
+ Foo::Wadus
+end
+```
+
+or add `Foo` to the nesting:
+
+```ruby
+module Foo
+ class Bar
+ Wadus
+ end
+end
+```
+
+#### Concerns
+
+You can autoload and eager load from a standard structure like
+
+```
+app/models
+app/models/concerns
+```
+
+In that case, `app/models/concerns` is assumed to be a root directory (because it belongs to the autoload paths), and it is ignored as namespace. So, `app/models/concerns/foo.rb` should define `Foo`, not `Concerns::Foo`.
+
+The `Concerns::` namespace worked with the classic autoloader as a side-effect of the implementation, but it was not really an intended behavior. An application using `Concerns::` needs to rename those classes and modules to be able to run in `zeitwerk` mode.
+
+#### Spring and the `test` Environment
+
+Spring reloads the application code if something changes. In the `test` environment you need to enable reloading for that to work:
+
+```ruby
+# config/environments/test.rb
+
+config.cache_classes = false
+```
+
+Otherwise you'll get this error:
+
+```
+reloading is disabled because config.cache_classes is true
+```
+
+#### Bootsnap
+
+Bootsnap should be at least version 1.4.2.
+
+In addition to that, Bootsnap needs to disable the iseq cache due to a bug in the interpreter if running Ruby 2.5. Please make sure to depend on at least Bootsnap 1.4.4 in that case.
+
+#### `config.add_autoload_paths_to_load_path`
+
+The new configuration point
+
+```ruby
+config.add_autoload_paths_to_load_path
+```
+
+is `true` by default for backwards compatibility, but allows you to opt-out from adding the autoload paths to `$LOAD_PATH`.
+
+This makes sense in most applications, since you never should require a file in `app/models`, for example, and Zeitwerk only uses absolute file names internally.
+
+By opting-out you optimize `$LOAD_PATH` lookups (less directories to check), and save Bootsnap work and memory consumption, since it does not need to build an index for these directories.
+
+#### Thread-safety
+
+In classic mode constant autoloading is not thread-safe, though Rails has locks in place for example to make web requests thread-safe when autoloading is enabled, as it is common in `development` mode.
+
+Constant autoloading is thread-safe in `zeitwerk` mode. For example, you can now autoload in multi-threaded scripts executed by the `runner` command.
+
+#### Globs in config.autoload_paths
+
+Beware of configurations like
+
+```ruby
+config.autoload_paths += Dir["#{config.root}/lib/**/"]
+```
+
+Every element of `config.autoload_paths` should represent the top-level namespace (`Object`) and they cannot be nested in consequence (with the exception of `concerns` directories explained above).
+
+To fix this, just remove the wildcards:
+
+```ruby
+config.autoload_paths << "#{config.root}/lib"
+```
+
Upgrading from Rails 5.1 to Rails 5.2
-------------------------------------