如何在FactoryBot中使用驼峰式ID(camelCase ID)建立关联?
你的问题核心在于ActiveRecord模型和FactoryBot都默认遵循Rails的下划线外键惯例,但你的表用的是animalId这种驼峰字段,导致关联逻辑和验证都错位了。咱们一步步来修复:
第一步:先修正ActiveRecord模型的关联配置
这是最关键的前提——如果模型没正确识别外键,不管FactoryBot怎么写,Rails的验证都会报错。
在你的Animal模型里,指定关联的外键:
class Animal < ActiveRecord::Base has_many :animal_locations, foreign_key: 'animalId' end
在AnimalLocation模型里,同样指定belongs_to的外键:
class AnimalLocation < ActiveRecord::Base belongs_to :animal, foreign_key: 'animalId' end
这样Rails就知道,AnimalLocation的animal关联对应的是表中的animalId字段,而不是默认的animal_id。
第二步:调整FactoryBot的关联写法
现在模型配置对了,FactoryBot的写法就简单了,推荐两种可靠的方式:
方式1:用association方法指定外键(最简洁)
直接在工厂里通过foreign_key参数告诉FactoryBot,把关联对象的ID赋值到animalId字段:
factory :animal_location, class: AnimalLocation do id { SecureRandom.uuid } name { "Oak Tree Grove" } # 明确指定外键字段,FactoryBot会自动创建Animal并赋值到animalId association :animal, factory: :animal, foreign_key: 'animalId' end
方式2:用before钩子(适合更复杂的场景)
如果你需要更灵活的逻辑,比如先创建Animal再处理其他操作,也可以用钩子,但要注意直接赋值关联对象(而不是手动写animalId),因为模型已经配置了外键,Rails会自动帮你映射到animalId字段:
factory :animal_location, class: AnimalLocation do id { SecureRandom.uuid } name { "Oak Tree Grove" } before(:create) do |location| # 直接赋值关联对象,Rails会自动把animal.id写入animalId location.animal = create(:animal) end end
为什么你之前的钩子写法会报错?
你之前手动赋值animal_location.animalId = animal.id,但因为模型的belongs_to :animal没指定foreign_key,Rails默认会检查animal_id字段是否存在对应的Animal——而你的表根本没有这个字段,所以触发了Validation failed: Animal must exist的错误。现在模型配置了正确的外键,这个问题就解决了。
内容的提问来源于stack exchange,提问作者SegFaultDev

