如何为互相依赖的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
相关产品推荐
相关产品推荐

