← Blog

Rails 7 adds build/create constructors to has_one :through

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.

Akanksha Jain avatar
Written byAkanksha Jain

Newsletter

Stay up to date with our blogs.

Subscribe to receive email notifications for new blog posts.

Get in touch

Got a project in mind?

Talk to us