This blog is part of our Rails 7 series.
What are build_association and create_association constructors?
When we declare either a belongs_to or has_one association, the declaring class automatically gains the following methods related to the association:
- build_association(attributes = {})
- create_association(attributes = {})
In the above methods _association is replaced with the symbol(association name) passed as the first argument while declaring the associations. For example:
1class Book < ApplicationRecord 2 belongs_to :author 3end 4 5@book.build_author(name: 'John Doe', email: '[email protected]') 6#=> Returns a new Author object, instantiated with the passed attributes 7#=> Links through the book's object foreign key 8#=> New author object won't be saved in the database 9 10@book.create_author(name: 'John Doe', email: '[email protected]') 11#=> Returns a new Author object, instantiated with the passed attributes 12#=> Links through the book's object foreign key 13#=> The new author object will be saved in the database after passing all of the validations specified on the Author model
Before Rails 7
The build_association and create_association constructors were only supported by belongs_to and has_one associations.
Consider the example below. We have a model, Member, that has a has_one association with the CurrentMembership model. It also has a has_one :through association with the Club model.
1class Member < ApplicationRecord 2 has_one :current_membership 3 has_one :club, through: :current_membership 4end 5 6@member.build_club 7#=> NoMethodError (undefined method `build_club' for #<Member:0x00007f9ea2ebd3e8>) 8#=> Did you mean? build_current_membership 9 10@member.create_club 11#=> NoMethodError (undefined method `create_club' for #<Member:0x00007f9ea2ebd3e8>) 12#=> Did you mean? create_current_membership
After Rails 7
Users are allowed to use constructors (build_association and create_association) on has_one :through associations along with belongs_to and has_one associations.
1class Member < ApplicationRecord 2 has_one :current_membership 3 has_one :club, through: :current_membership 4end 5 6@member.build_club 7#=> #<Club:0x00007f9ea01a8ce0> 8 9@member.create_club 10#=> #<Club:0x00007f9ea01a8ce0>
Check out this pull request for more details.