Rails 5.2中FactoryBot生成实例无ID和时间戳问题求助
问题:Rails 5.2中FactoryBot.build生成的实例无ID和时间戳
我正在使用Rails 5.2开发项目,定义了如下Flashcard和Box的FactoryBot:
Flashcard Factory 定义
FactoryBot.define do factory :flashcard do question { Faker::Quote.matz } time { Faker::Number.between(from: 1, to: 300) } association :box end end
Box Factory 定义
FactoryBot.define do factory :box do mod_p { Faker::Number.between(from: 1, to: 10) } box_number { Faker::Number.between(from: 1, to: 10) } end end
测试中创建实例的代码:
box1 = FactoryBot.build(:box, box_number: 1) box2 = FactoryBot.build(:box, box_number: 2) box3 = FactoryBot.build(:box, box_number: 3) subject(:flashcard) {FactoryBot.build(:flashcard, box: box2)}
但生成的实例没有ID和时间戳,请问原因是什么?我已查阅Rails 6相关资料,但不适用于当前项目。
解答
核心原因是你使用了FactoryBot.build方法:
- 这个方法仅在内存中构建模型实例,不会将数据持久化到数据库
- Rails中ID是数据库插入记录时自动生成的,未保存的实例自然没有ID
created_at、updated_at这类时间戳,默认也是在实例保存到数据库时由Rails自动赋值的,未持久化的实例不会有这些值
解决方法
需要真实ID和时间戳时,改用
FactoryBot.create
该方法会将实例保存到数据库,自动生成ID和时间戳:box1 = FactoryBot.create(:box, box_number: 1) box2 = FactoryBot.create(:box, box_number: 2) subject(:flashcard) {FactoryBot.create(:flashcard, box: box2)}无需持久化但要模拟时间戳,手动设置
如果不想保存到数据库,可在Factory中手动定义时间戳字段:FactoryBot.define do factory :box do mod_p { Faker::Number.between(from: 1, to: 10) } box_number { Faker::Number.between(from: 1, to: 10) } created_at { Time.current } updated_at { Time.current } end end注:这种方式无法生成真实数据库ID,除非你手动指定
id字段的值。
内容的提问来源于stack exchange,提问作者LeeXiuLong
相关产品推荐
相关产品推荐

