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

Akanksha Jain

Akanksha Jain

April 6, 2021

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:

class Book < ApplicationRecord
  belongs_to :author
end

@book.build_author(name: 'John Doe', email: '[email protected]')
#=> Returns a new Author object, instantiated with the passed attributes
#=> Links through the book's object foreign key
#=> New author object won't be saved in the database

@book.create_author(name: 'John Doe', email: '[email protected]')
#=> Returns a new Author object, instantiated with the passed attributes
#=> Links through the book's object foreign key
#=> 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.

class Member < ApplicationRecord
  has_one :current_membership
  has_one :club, through: :current_membership
end

@member.build_club
#=> NoMethodError (undefined method `build_club' for #<Member:0x00007f9ea2ebd3e8>)
#=> Did you mean?  build_current_membership

@member.create_club
#=> NoMethodError (undefined method `create_club' for #<Member:0x00007f9ea2ebd3e8>)
#=> 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.

class Member < ApplicationRecord
  has_one :current_membership
  has_one :club, through: :current_membership
end

@member.build_club
#=> #<Club:0x00007f9ea01a8ce0>

@member.create_club
#=> #<Club:0x00007f9ea01a8ce0>

Check out this pull request for more details.

If this blog was helpful, check out our full blog archive.

Stay up to date with our blogs.

Subscribe to receive email notifications for new blog posts.