Back to Blog

Rails 7 allows constructors (build_association and create_association) on has_one :through associations

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:

  1. build_association(attributes = {})
  2. 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: 'john_doe@example.com')
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: 'john_doe@example.com')
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.


You might also like

If you liked this blog post, check out similar ones from BigBinary