FactoryBot关联创建重复父对象问题求助(Rails 7.1)
问题原因解析
1. association方法的默认行为导致额外创建Program
FactoryBot的association方法在创建关联对象时,默认会独立处理关联依赖——如果你的ProgramMedia模型是belongs_to :program,且工厂未指定关联的Program实例,那么当你在Program工厂的trait里直接写association :main_program_media时,FactoryBot会自动创建一个新的Program实例来绑定这个ProgramMedia,而不是把它关联到你正在创建的那个Program上。
整个执行流程是:
- 启动创建第一个Program实例(记为Program A)
- 执行
association :main_program_media,触发创建ProgramMedia - 因为ProgramMedia必须关联Program,FactoryBot会额外创建第二个Program实例(Program B),并把ProgramMedia绑定到Program B上
- 最终Program A和Program B都会被保存,而你期望的主媒体却关联在Program B上,这就出现了两个Program的问题。
2. after(:build)为什么能正常工作
改用after(:build)钩子后,你是在当前Program实例已经构建完成的前提下,手动创建ProgramMedia并绑定到这个实例上:
trait :with_main_program_media do after(:build) do |program| program.main_program_media = build(:program_media, program: program) end end
这个流程里,所有操作都围绕同一个Program实例展开,不会触发FactoryBot自动创建新的Program,自然就不会出现重复创建的问题。
额外技巧:用association也能实现正确关联
如果不想改用钩子,也可以在association里显式指定关联的Program为当前实例,通过lambda传递参数:
trait :with_main_program_media do association :main_program_media, factory: :program_media, program: -> { self } end
这里的-> { self }会引用正在构建的Program实例,让ProgramMedia直接绑定到它,避免额外创建新的Program。
内容的提问来源于stack exchange,提问作者Leticia Esperon
相关产品推荐
相关产品推荐

