mirror of https://github.com/rails/rails
Move load hooks section to the configuration guide
Those also applies to applications, so they should not be in a guide specific for engines.
This commit is contained in:
parent
8922180af5
commit
247c892150
|
@ -3453,6 +3453,135 @@ NOTE: There is no guarantee that your initializers will run after all the gem
|
|||
initializers, so any initialization code that depends on a given gem having been
|
||||
initialized should go into a `config.after_initialize` block.
|
||||
|
||||
Load Hooks
|
||||
----------------------------
|
||||
|
||||
Rails code can often be referenced on load of an application. Rails is responsible for the load order of these frameworks, so when you load frameworks, such as `ActiveRecord::Base`, prematurely you are violating an implicit contract your application has with Rails. Moreover, by loading code such as `ActiveRecord::Base` on boot of your application you are loading entire frameworks which may slow down your boot time and could cause conflicts with load order and boot of your application.
|
||||
|
||||
Load and configuration hooks are the API that allow you to hook into this initialization process without violating the load contract with Rails. This will also mitigate boot performance degradation and avoid conflicts.
|
||||
|
||||
### Avoid Loading Rails Frameworks
|
||||
|
||||
Since Ruby is a dynamic language, some code will cause different Rails frameworks to load. Take this snippet for instance:
|
||||
|
||||
```ruby
|
||||
ActiveRecord::Base.include(MyActiveRecordHelper)
|
||||
```
|
||||
|
||||
This snippet means that when this file is loaded, it will encounter `ActiveRecord::Base`. This encounter causes Ruby to look for the definition of that constant and will require it. This causes the entire Active Record framework to be loaded on boot.
|
||||
|
||||
`ActiveSupport.on_load` is a mechanism that can be used to defer the loading of code until it is actually needed. The snippet above can be changed to:
|
||||
|
||||
```ruby
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
include MyActiveRecordHelper
|
||||
end
|
||||
```
|
||||
|
||||
This new snippet will only include `MyActiveRecordHelper` when `ActiveRecord::Base` is loaded.
|
||||
|
||||
### When are Hooks called?
|
||||
|
||||
In the Rails framework these hooks are called when a specific library is loaded. For example, when `ActionController::Base` is loaded, the `:action_controller_base` hook is called. This means that all `ActiveSupport.on_load` calls with `:action_controller_base` hooks will be called in the context of `ActionController::Base` (that means `self` will be an `ActionController::Base`).
|
||||
|
||||
### Modifying Code to Use Load Hooks
|
||||
|
||||
Modifying code is generally straightforward. If you have a line of code that refers to a Rails framework such as `ActiveRecord::Base` you can wrap that code in a load hook.
|
||||
|
||||
**Modifying calls to `include`**
|
||||
|
||||
```ruby
|
||||
ActiveRecord::Base.include(MyActiveRecordHelper)
|
||||
```
|
||||
|
||||
becomes
|
||||
|
||||
```ruby
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
# self refers to ActiveRecord::Base here,
|
||||
# so we can call .include
|
||||
include MyActiveRecordHelper
|
||||
end
|
||||
```
|
||||
|
||||
**Modifying calls to `prepend`**
|
||||
|
||||
```ruby
|
||||
ActionController::Base.prepend(MyActionControllerHelper)
|
||||
```
|
||||
|
||||
becomes
|
||||
|
||||
```ruby
|
||||
ActiveSupport.on_load(:action_controller_base) do
|
||||
# self refers to ActionController::Base here,
|
||||
# so we can call .prepend
|
||||
prepend MyActionControllerHelper
|
||||
end
|
||||
```
|
||||
|
||||
**Modifying calls to class methods**
|
||||
|
||||
```ruby
|
||||
ActiveRecord::Base.include_root_in_json = true
|
||||
```
|
||||
|
||||
becomes
|
||||
|
||||
```ruby
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
# self refers to ActiveRecord::Base here
|
||||
self.include_root_in_json = true
|
||||
end
|
||||
```
|
||||
|
||||
### Available Load Hooks
|
||||
|
||||
These are the load hooks you can use in your own code. To hook into the initialization process of one of the following classes use the available hook.
|
||||
|
||||
| Class | Hook |
|
||||
| -------------------------------------| ------------------------------------ |
|
||||
| `ActionCable` | `action_cable` |
|
||||
| `ActionCable::Channel::Base` | `action_cable_channel` |
|
||||
| `ActionCable::Connection::Base` | `action_cable_connection` |
|
||||
| `ActionCable::Connection::TestCase` | `action_cable_connection_test_case` |
|
||||
| `ActionController::API` | `action_controller_api` |
|
||||
| `ActionController::API` | `action_controller` |
|
||||
| `ActionController::Base` | `action_controller_base` |
|
||||
| `ActionController::Base` | `action_controller` |
|
||||
| `ActionController::TestCase` | `action_controller_test_case` |
|
||||
| `ActionDispatch::IntegrationTest` | `action_dispatch_integration_test` |
|
||||
| `ActionDispatch::Response` | `action_dispatch_response` |
|
||||
| `ActionDispatch::Request` | `action_dispatch_request` |
|
||||
| `ActionDispatch::SystemTestCase` | `action_dispatch_system_test_case` |
|
||||
| `ActionMailbox::Base` | `action_mailbox` |
|
||||
| `ActionMailbox::InboundEmail` | `action_mailbox_inbound_email` |
|
||||
| `ActionMailbox::Record` | `action_mailbox_record` |
|
||||
| `ActionMailbox::TestCase` | `action_mailbox_test_case` |
|
||||
| `ActionMailer::Base` | `action_mailer` |
|
||||
| `ActionMailer::TestCase` | `action_mailer_test_case` |
|
||||
| `ActionText::Content` | `action_text_content` |
|
||||
| `ActionText::Record` | `action_text_record` |
|
||||
| `ActionText::RichText` | `action_text_rich_text` |
|
||||
| `ActionText::EncryptedRichText` | `action_text_encrypted_rich_text` |
|
||||
| `ActionView::Base` | `action_view` |
|
||||
| `ActionView::TestCase` | `action_view_test_case` |
|
||||
| `ActiveJob::Base` | `active_job` |
|
||||
| `ActiveJob::TestCase` | `active_job_test_case` |
|
||||
| `ActiveModel::Model` | `active_model` |
|
||||
| `ActiveRecord::Base` | `active_record` |
|
||||
| `ActiveRecord::TestFixtures` | `active_record_fixtures` |
|
||||
| `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter` | `active_record_postgresqladapter` |
|
||||
| `ActiveRecord::ConnectionAdapters::Mysql2Adapter` | `active_record_mysql2adapter` |
|
||||
| `ActiveRecord::ConnectionAdapters::TrilogyAdapter` | `active_record_trilogyadapter` |
|
||||
| `ActiveRecord::ConnectionAdapters::SQLite3Adapter` | `active_record_sqlite3adapter` |
|
||||
| `ActiveStorage::Attachment` | `active_storage_attachment` |
|
||||
| `ActiveStorage::VariantRecord` | `active_storage_variant_record` |
|
||||
| `ActiveStorage::Blob` | `active_storage_blob` |
|
||||
| `ActiveStorage::Record` | `active_storage_record` |
|
||||
| `ActiveSupport::TestCase` | `active_support_test_case` |
|
||||
| `i18n` | `i18n` |
|
||||
|
||||
Initialization Events
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -1369,157 +1369,3 @@ module MyEngine
|
|||
end
|
||||
end
|
||||
```
|
||||
|
||||
Load and Configuration Hooks
|
||||
----------------------------
|
||||
|
||||
Rails code can often be referenced on load of an application. Rails is responsible for the load order of these frameworks, so when you load frameworks, such as `ActiveRecord::Base`, prematurely you are violating an implicit contract your application has with Rails. Moreover, by loading code such as `ActiveRecord::Base` on boot of your application you are loading entire frameworks which may slow down your boot time and could cause conflicts with load order and boot of your application.
|
||||
|
||||
Load and configuration hooks are the API that allow you to hook into this initialization process without violating the load contract with Rails. This will also mitigate boot performance degradation and avoid conflicts.
|
||||
|
||||
### Avoid Loading Rails Frameworks
|
||||
|
||||
Since Ruby is a dynamic language, some code will cause different Rails frameworks to load. Take this snippet for instance:
|
||||
|
||||
```ruby
|
||||
ActiveRecord::Base.include(MyActiveRecordHelper)
|
||||
```
|
||||
|
||||
This snippet means that when this file is loaded, it will encounter `ActiveRecord::Base`. This encounter causes Ruby to look for the definition of that constant and will require it. This causes the entire Active Record framework to be loaded on boot.
|
||||
|
||||
`ActiveSupport.on_load` is a mechanism that can be used to defer the loading of code until it is actually needed. The snippet above can be changed to:
|
||||
|
||||
```ruby
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
include MyActiveRecordHelper
|
||||
end
|
||||
```
|
||||
|
||||
This new snippet will only include `MyActiveRecordHelper` when `ActiveRecord::Base` is loaded.
|
||||
|
||||
### When are Hooks called?
|
||||
|
||||
In the Rails framework these hooks are called when a specific library is loaded. For example, when `ActionController::Base` is loaded, the `:action_controller_base` hook is called. This means that all `ActiveSupport.on_load` calls with `:action_controller_base` hooks will be called in the context of `ActionController::Base` (that means `self` will be an `ActionController::Base`).
|
||||
|
||||
### Modifying Code to Use Load Hooks
|
||||
|
||||
Modifying code is generally straightforward. If you have a line of code that refers to a Rails framework such as `ActiveRecord::Base` you can wrap that code in a load hook.
|
||||
|
||||
**Modifying calls to `include`**
|
||||
|
||||
```ruby
|
||||
ActiveRecord::Base.include(MyActiveRecordHelper)
|
||||
```
|
||||
|
||||
becomes
|
||||
|
||||
```ruby
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
# self refers to ActiveRecord::Base here,
|
||||
# so we can call .include
|
||||
include MyActiveRecordHelper
|
||||
end
|
||||
```
|
||||
|
||||
**Modifying calls to `prepend`**
|
||||
|
||||
```ruby
|
||||
ActionController::Base.prepend(MyActionControllerHelper)
|
||||
```
|
||||
|
||||
becomes
|
||||
|
||||
```ruby
|
||||
ActiveSupport.on_load(:action_controller_base) do
|
||||
# self refers to ActionController::Base here,
|
||||
# so we can call .prepend
|
||||
prepend MyActionControllerHelper
|
||||
end
|
||||
```
|
||||
|
||||
**Modifying calls to class methods**
|
||||
|
||||
```ruby
|
||||
ActiveRecord::Base.include_root_in_json = true
|
||||
```
|
||||
|
||||
becomes
|
||||
|
||||
```ruby
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
# self refers to ActiveRecord::Base here
|
||||
self.include_root_in_json = true
|
||||
end
|
||||
```
|
||||
|
||||
### Available Load Hooks
|
||||
|
||||
These are the load hooks you can use in your own code. To hook into the initialization process of one of the following classes use the available hook.
|
||||
|
||||
| Class | Hook |
|
||||
| -------------------------------------| ------------------------------------ |
|
||||
| `ActionCable` | `action_cable` |
|
||||
| `ActionCable::Channel::Base` | `action_cable_channel` |
|
||||
| `ActionCable::Connection::Base` | `action_cable_connection` |
|
||||
| `ActionCable::Connection::TestCase` | `action_cable_connection_test_case` |
|
||||
| `ActionController::API` | `action_controller_api` |
|
||||
| `ActionController::API` | `action_controller` |
|
||||
| `ActionController::Base` | `action_controller_base` |
|
||||
| `ActionController::Base` | `action_controller` |
|
||||
| `ActionController::TestCase` | `action_controller_test_case` |
|
||||
| `ActionDispatch::IntegrationTest` | `action_dispatch_integration_test` |
|
||||
| `ActionDispatch::Response` | `action_dispatch_response` |
|
||||
| `ActionDispatch::Request` | `action_dispatch_request` |
|
||||
| `ActionDispatch::SystemTestCase` | `action_dispatch_system_test_case` |
|
||||
| `ActionMailbox::Base` | `action_mailbox` |
|
||||
| `ActionMailbox::InboundEmail` | `action_mailbox_inbound_email` |
|
||||
| `ActionMailbox::Record` | `action_mailbox_record` |
|
||||
| `ActionMailbox::TestCase` | `action_mailbox_test_case` |
|
||||
| `ActionMailer::Base` | `action_mailer` |
|
||||
| `ActionMailer::TestCase` | `action_mailer_test_case` |
|
||||
| `ActionText::Content` | `action_text_content` |
|
||||
| `ActionText::Record` | `action_text_record` |
|
||||
| `ActionText::RichText` | `action_text_rich_text` |
|
||||
| `ActionText::EncryptedRichText` | `action_text_encrypted_rich_text` |
|
||||
| `ActionView::Base` | `action_view` |
|
||||
| `ActionView::TestCase` | `action_view_test_case` |
|
||||
| `ActiveJob::Base` | `active_job` |
|
||||
| `ActiveJob::TestCase` | `active_job_test_case` |
|
||||
| `ActiveModel::Model` | `active_model` |
|
||||
| `ActiveRecord::Base` | `active_record` |
|
||||
| `ActiveRecord::TestFixtures` | `active_record_fixtures` |
|
||||
| `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter` | `active_record_postgresqladapter` |
|
||||
| `ActiveRecord::ConnectionAdapters::Mysql2Adapter` | `active_record_mysql2adapter` |
|
||||
| `ActiveRecord::ConnectionAdapters::TrilogyAdapter` | `active_record_trilogyadapter` |
|
||||
| `ActiveRecord::ConnectionAdapters::SQLite3Adapter` | `active_record_sqlite3adapter` |
|
||||
| `ActiveStorage::Attachment` | `active_storage_attachment` |
|
||||
| `ActiveStorage::VariantRecord` | `active_storage_variant_record` |
|
||||
| `ActiveStorage::Blob` | `active_storage_blob` |
|
||||
| `ActiveStorage::Record` | `active_storage_record` |
|
||||
| `ActiveSupport::TestCase` | `active_support_test_case` |
|
||||
| `i18n` | `i18n` |
|
||||
|
||||
### Available Configuration Hooks
|
||||
|
||||
Configuration hooks do not hook into any particular framework, but instead they run in context of the entire application.
|
||||
|
||||
| Hook | Use Case |
|
||||
| ---------------------- | ---------------------------------------------------------------------------------- |
|
||||
| `before_configuration` | First configurable block to run. Called before any initializers are run. |
|
||||
| `before_initialize` | Second configurable block to run. Called before frameworks initialize. |
|
||||
| `before_eager_load` | Third configurable block to run. Does not run if [`config.eager_load`][] set to false. |
|
||||
| `after_initialize` | Last configurable block to run. Called after frameworks initialize. |
|
||||
|
||||
Configuration hooks can be called in the Engine class.
|
||||
|
||||
```ruby
|
||||
module Blorgh
|
||||
class Engine < ::Rails::Engine
|
||||
config.before_configuration do
|
||||
puts 'I am called before any initializers'
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
[`config.eager_load`]: configuring.html#config-eager-load
|
||||
|
|
Loading…
Reference in New Issue