I have a rails 7.1 app.
A program can have many program_media and one of them is the main_program_media:
class Program < ApplicationRecord
has_many :program_medias,
inverse_of: :program, dependent: :destroy
class_name: 'ProgramMedia',
inverse_of: :program,
dependent: :destroy
has_one :main_program_media, -> { main },
class_name: 'ProgramMedia',
inverse_of: :program,
dependent: :destroy
end
class ProgramMedia < ApplicationRecord
belongs_to :program, inverse_of: :program_medias
scope :main, -> { where(main: true) }
end
I have a trait in my program factory so that a main program media is created:
FactoryBot.define do
factory :program do
trait :with_main_program_media do
association :main_program_media, factory: %i[program_media main]
end
end
end
However, we are seeing that the following line:
FactoryBot.create(:program, :with_main_program_media)
creates not 1 but 2 programs. The program_media's program is a different one (not the one that invoked the factory).
I can fix it by changing the factory trait to:
trait :with_main_program_media do
after(:build) do |program|
program.main_program_media = build(:program_media, :main) # notice no need to manually assign the program which means associations are correctly set up
end
end
but I think there's an underlying issue with how factory bot is working, because I would have expected the first to work in the same way as the second. What am I missing?
The issue is the same with a has_one, and the fact that I'm using a scope in the association doesn't seem to change anything.