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

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自动赋值的,未持久化的实例不会有这些值

解决方法

  1. 需要真实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)}
    
  2. 无需持久化但要模拟时间戳,手动设置
    如果不想保存到数据库,可在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 22:57:20