Interconnected associations

There are limitless ways objects might be interconnected, and factory_bot may not always be suited to handle those relationships. In some cases it makes sense to use factory_bot to build each individual object, and then to write helper methods in plain Ruby to tie those objects together.

That said, some more complex, interconnected relationships can be built in factory_bot using inline associations with reference to the instance being built.

Let's say your models look like this, where an associated Student and Profile should both belong to the same School:

class Student < ApplicationRecord
  belongs_to :school
  has_one :profile
end

class Profile < ApplicationRecord
  belongs_to :school
  belongs_to :student
end

class School < ApplicationRecord
  has_many :students
  has_many :profiles
end

We can ensure the student and profile are connected to each other and to the same school with a factory like this:

FactoryBot.define do
  factory :student do
    school
    profile { association :profile, student: instance, school: school }
  end

  factory :profile do
    school
    student { association :student, profile: instance, school: school }
  end

  factory :school
end

Note that this approach works with build, build_stubbed, and create, but the associations will return nil when using attributes_for.

Also, note that if you assign any attributes inside a custom initialize_with (e.g. initialize_with { new(**attributes) }), those attributes should not refer to instance, since it will be nil.