mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Clarify Bi-directional Associations docs
Rails automatically finds bi-directional associations between models with well-named associations. However, when using non-standard naming, you have to use :inverse_of to explicitly tell Rails about the bi- directional association. With reference to #27516 [ci skip]
This commit is contained in:
parent
e42cbb7d31
commit
186327f74a
1 changed files with 54 additions and 36 deletions
|
@ -709,56 +709,74 @@ class Book < ApplicationRecord
|
|||
end
|
||||
```
|
||||
|
||||
By default, Active Record doesn't know about the connection between these associations. This can lead to two copies of an object getting out of sync:
|
||||
Active Record will attempt to automatically identify that these two models share a bi-directional association based on the association name. In this way, Active Record will only load one copy of the `Author` object, making your application more efficient and preventing inconsistent data:
|
||||
|
||||
```ruby
|
||||
a = Author.first
|
||||
b = a.books.first
|
||||
a.first_name == b.author.first_name # => true
|
||||
a.first_name = 'Manny'
|
||||
a.first_name == b.author.first_name # => false
|
||||
```
|
||||
|
||||
This happens because `a` and `b.author` are two different in-memory representations of the same data, and neither one is automatically refreshed from changes to the other. Active Record provides the `:inverse_of` option so that you can inform it of these relations:
|
||||
|
||||
```ruby
|
||||
class Author < ApplicationRecord
|
||||
has_many :books, inverse_of: :author
|
||||
end
|
||||
|
||||
class Book < ApplicationRecord
|
||||
belongs_to :author, inverse_of: :books
|
||||
end
|
||||
```
|
||||
|
||||
With these changes, Active Record will only load one copy of the author object, preventing inconsistencies and making your application more efficient:
|
||||
|
||||
```ruby
|
||||
a = Author.first
|
||||
b = a.books.first
|
||||
a.first_name == b.author.first_name # => true
|
||||
a.first_name = 'Manny'
|
||||
a.first_name = 'David'
|
||||
a.first_name == b.author.first_name # => true
|
||||
```
|
||||
|
||||
There are a few limitations to `inverse_of` support:
|
||||
|
||||
* They do not work with `:through` associations.
|
||||
* They do not work with `:polymorphic` associations.
|
||||
* They do not work with `:as` associations.
|
||||
* For `belongs_to` associations, `has_many` inverse associations are ignored.
|
||||
|
||||
Every association will attempt to automatically find the inverse association
|
||||
and set the `:inverse_of` option heuristically (based on the association name).
|
||||
Most associations with standard names will be supported. However, associations
|
||||
that contain the following options will not have their inverses set
|
||||
automatically:
|
||||
Active Record supports automatic identification for most associations with standard names. However, Active Record will not automatically identify bi-directional associations that contain any of the following options:
|
||||
|
||||
* `:conditions`
|
||||
* `:through`
|
||||
* `:polymorphic`
|
||||
* `:class_name`
|
||||
* `:foreign_key`
|
||||
|
||||
For example, consider the following model declarations:
|
||||
|
||||
```ruby
|
||||
class Author < ApplicationRecord
|
||||
has_many :books
|
||||
end
|
||||
|
||||
class Book < ApplicationRecord
|
||||
belongs_to :writer, class_name: 'Author', foreign_key: 'author_id'
|
||||
end
|
||||
```
|
||||
|
||||
Active Record will no longer automatically recognize the bi-directional association:
|
||||
|
||||
```ruby
|
||||
a = Author.first
|
||||
b = a.books.first
|
||||
a.first_name == b.writer.first_name # => true
|
||||
a.first_name = 'David'
|
||||
a.first_name == b.writer.first_name # => false
|
||||
```
|
||||
|
||||
Active Record provides the `:inverse_of` option so you can explicitly declare bi-directional associations:
|
||||
|
||||
```ruby
|
||||
class Author < ApplicationRecord
|
||||
has_many :books, inverse_of: 'writer'
|
||||
end
|
||||
|
||||
class Book < ApplicationRecord
|
||||
belongs_to :writer, class_name: 'Author', foreign_key: 'author_id'
|
||||
end
|
||||
```
|
||||
|
||||
By including the `:inverse_of` option in the `has_many` association declaration, Active Record will now recognize the bi-directional association:
|
||||
|
||||
```ruby
|
||||
a = Author.first
|
||||
b = a.books.first
|
||||
a.first_name == b.writer.first_name # => true
|
||||
a.first_name = 'David'
|
||||
a.first_name == b.writer.first_name # => true
|
||||
```
|
||||
|
||||
There are a few limitations to `:inverse_of` support:
|
||||
|
||||
* They do not work with `:through` associations.
|
||||
* They do not work with `:polymorphic` associations.
|
||||
* They do not work with `:as` associations.
|
||||
|
||||
Detailed Association Reference
|
||||
------------------------------
|
||||
|
||||
|
|
Loading…
Reference in a new issue