You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为互相依赖的Survey与Question模型创建有效工厂?

如何为互相依赖的Survey和Question模型创建有效的FactoryBot工厂?

这种互相依赖的模型验证确实容易在写工厂的时候卡壳,毕竟两边都有必填关联的要求,我来给你分享个靠谱的实现方案:

1. 定义Survey工厂

我们需要确保每次创建Survey时,自动带上至少一个Question来满足validates_length_of :questions, minimum: 1的验证。这里可以用FactoryBot的回调和临时属性来灵活控制:

FactoryBot.define do
  factory :survey do
    title { "用户满意度调研" }

    # 临时属性:控制要创建的Question数量,默认1个(满足最小要求)
    transient do
      question_count { 1 }
    end

    # 构建阶段就关联Question,确保未保存的Survey对象也能通过验证
    after(:build) do |survey, evaluator|
      evaluator.question_count.times do
        survey.questions << build(:question, survey: survey)
      end
    end

    # 创建阶段批量生成Question(如果需要多于1个的话)
    after(:create) do |survey, evaluator|
      # 因为build阶段已经创建了1个,所以这里只需要补剩下的
      create_list(:question, evaluator.question_count - 1, survey: survey)
    end
  end
end

2. 定义Question工厂

Question必须属于某个Survey,所以我们在工厂里默认关联一个新的Survey,也支持传入已有的Survey对象来复用:

FactoryBot.define do
  factory :question do
    title { "你对产品的整体满意度如何?" }
    # 默认自动创建并关联一个Survey,也可以手动传入survey: existing_survey覆盖
    survey { association :survey }
  end
end

3. 额外技巧:测试验证逻辑的Trait

如果你需要测试Survey没有Question时的验证失败场景,可以给Survey工厂加一个trait来跳过自动创建Question:

FactoryBot.define do
  factory :survey do
    # ... 上面的原有代码 ...

    trait :without_questions do
      after(:build) do |survey|
        survey.questions.clear
      end
    end
  end
end

使用的时候就可以这么写:build(:survey, :without_questions),这个对象会因为没有关联Question而无法通过验证,刚好用来测试你的验证规则是否生效。

这样不管是单独创建Survey、单独创建Question,还是创建带有多个Question的Survey,都能顺利通过模型的验证啦!

内容的提问来源于stack exchange,提问作者dpst

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:34:33