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

Merge pull request #41438 from soartec-lab/task/add-document-for-ar-eager-load-method

Added guides for Active Record `preload` and `eager_load`. [skip ci]
This commit is contained in:
Rafael França 2021-02-15 18:24:24 -05:00 committed by GitHub
commit 907cb05dce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1359,9 +1359,19 @@ This code looks fine at the first sight. But the problem lies within the total n
**Solution to N + 1 queries problem**
Active Record lets you specify in advance all the associations that are going to be loaded. This is possible by specifying the [`includes`][] method of the `Model.find` call. With `includes`, Active Record ensures that all of the specified associations are loaded using the minimum possible number of queries.
Active Record lets you specify in advance all the associations that are going to be loaded.
Revisiting the above case, we could rewrite `Book.limit(10)` to eager load authors:
The methods are:
* [`includes`][]
* [`preload`][]
* [`eager_load`][]
### includes
With `includes`, Active Record ensures that all of the specified associations are loaded using the minimum possible number of queries.
Revisiting the above case using the `includes` method, we could rewrite `Book.limit(10)` to eager load authors:
```ruby
books = Book.includes(:author).limit(10)
@ -1374,12 +1384,12 @@ end
The above code will execute just **2** queries, as opposed to **11** queries in the previous case:
```sql
SELECT * FROM books LIMIT 10
SELECT authors.* FROM authors
WHERE (authors.id IN (1,2,3,4,5,6,7,8,9,10))
SELECT `books`* FROM `books` LIMIT 10
SELECT `authors`.* FROM `authors`
WHERE `authors`.`book_id` IN (1,2,3,4,5,6,7,8,9,10)
```
### Eager Loading Multiple Associations
#### Eager Loading Multiple Associations
Active Record lets you eager load any number of associations with a single `Model.find` call by using an array, hash, or a nested hash of array/hash with the `includes` method.
@ -1391,7 +1401,7 @@ Customer.includes(:orders, :reviews)
This loads all the customers and the associated orders and reviews for each.
#### Nested Associations Hash
##### Nested Associations Hash
```ruby
Customer.includes(orders: {books: [:supplier, :author]}).find(1)
@ -1399,7 +1409,7 @@ Customer.includes(orders: {books: [:supplier, :author]}).find(1)
This will find the customer with id 1 and eager load all of the associated orders for it, the books for all of the orders, and the author and supplier for each of the books.
### Specifying Conditions on Eager Loaded Associations
#### Specifying Conditions on Eager Loaded Associations
Even though Active Record lets you specify conditions on the eager loaded associations just like `joins`, the recommended way is to use [joins](#joining-tables) instead.
@ -1433,6 +1443,54 @@ returned.
NOTE: If an association is eager loaded as part of a join, any fields from a custom select clause will not be present on the loaded models.
This is because it is ambiguous whether they should appear on the parent record, or the child.
### preload
With `preload`, Active record ensures that loaded using a query for every specified association.
Revisiting the case where N + 1 was occurred using the `preload` method, we could rewrite `Book.limit(10)` to authors:
```ruby
books = Book.preload(:author).limit(10)
books.each do |book|
puts book.author.last_name
end
```
The above code will execute just **2** queries, as opposed to **11** queries in the previous case:
```sql
SELECT `books`* FROM `books` LIMIT 10
SELECT `authors`.* FROM `authors`
WHERE `authors`.`book_id` IN (1,2,3,4,5,6,7,8,9,10)
```
NOTE: The `preload` method using an array, hash, or a nested hash of array/hash in the same way as the includes method to load any number of associations with a single `Model.find` call. However, unlike the `includes` method, it is not possible to specify conditions for eager loaded associations.
### eager_load
With `eager_load`, Active record ensures that force eager loading by using `LEFT OUTER JOIN` for all specified associations.
Revisiting the case where N + 1 was occurred using the `eager_load` method, we could rewrite `Book.limit(10)` to authors:
```ruby
books = Book.eager_load(:author).limit(10)
books.each do |book|
puts book.author.last_name
end
```
The above code will execute just **2** queries, as opposed to **11** queries in the previous case:
```sql
SELECT DISTINCT `books`.`id` FROM `books` LEFT OUTER JOIN `authors` ON `authors`.`book_id` = `books`.`id` LIMIT 10
SELECT `books`.`id` AS t0_r0, `books`.`last_name` AS t0_r1, ...
FROM `books` LEFT OUTER JOIN `authors` ON `authors`.`book_id` = `books`.`id`
WHERE `books`.`id` IN (1,2,3,4,5,6,7,8,9,10)
```
NOTE: The `eager_load` method using an array, hash, or a nested hash of array/hash in the same way as the `includes` method to load any number of associations with a single `Model.find` call. Also, like the `includes` method, you can specify the conditions of the eager loaded association.
Scopes
------