FactoryGirl嵌套create_list遇关联类型不匹配,如何解决?
搞定ActiveRecord::AssociationTypeMismatch错误(HABTM关联场景)
嘿,这个问题我之前也踩过坑,其实根源很简单——你传参的时候不小心把数组套了两层,咱们一步步来解决:
问题出在哪?
你看,developers是用FactoryGirl.create_list(:user, 3)生成的,它本身就已经是一个User对象的数组了。但你创建project的时候写了users: [developers],这就等于把数组又包了一层,最终传给ActiveRecord的是[[user1, user2, user3]]。而你的Project和User是HABTM关联,users属性只接受单个User对象,或者一维的User数组,自然就触发类型不匹配的报错了。
核心修复方案
直接把developers数组平铺传给users就行,去掉外层的方括号:
let(:team_lead) { create(:user) } let(:developers) { FactoryGirl.create_list(:user, 3) } let(:project) { create(:project, team_lead: team_lead, users: developers) } # 去掉[],直接传developers
这样传进去的就是正常的一维User数组,ActiveRecord就能正确处理HABTM关联了,而且你也不用删掉developers变量,后续测试还能继续用它。
可选优化:给工厂加个快捷子工厂(方便复用)
如果你的测试里经常需要创建带多个开发者的项目,还可以给Project工厂加个子工厂,省得每次都手动传users参数:
修改spec/factory/project.rb:
FactoryGirl.define do factory :project do name { Faker::Name.name } team_lead nil factory :project_with_team_lead do team_lead end # 新增带开发者的子工厂,支持自定义数量 factory :project_with_developers do transient do developer_count 3 # 默认生成3个开发者 end after(:create) do |project, evaluator| # 创建指定数量的用户,并关联到当前项目 create_list(:user, evaluator.developer_count, projects: [project]) end end end end
之后在测试里就能这么用:
# 生成带3个开发者的项目(默认值) let(:project) { create(:project_with_developers, team_lead: team_lead) } # 或者自定义开发者数量,比如5个 let(:project) { create(:project_with_developers, team_lead: team_lead, developer_count: 5) }
这个优化是可选的,核心还是先把数组嵌套的问题解决掉~
内容的提问来源于stack exchange,提问作者Moses Liao GZ
相关产品推荐
相关产品推荐

