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

如何在FactoryBot trait中更新关联的Store对象?

在FactoryBot的Trait中更新关联对象属性的可行方案

当然可行,你当前的写法存在问题——直接传递哈希给store字段时,FactoryBot不会自动构建/创建符合该属性的关联对象,而是会尝试将哈希直接赋值给store,这会导致错误。以下是几种正确的实现方式:

方式1:直接构建/创建带指定属性的关联对象

如果Store已经有对应的FactoryBot工厂,你可以在trait里直接构建或创建带有目标属性的Store实例:

FactoryBot.define do
  factory :fruit do
    name { "Kiwi" }
    status { "available" }
    # 更健壮的写法:优先用已存在的Store,不存在则创建
    store { Store.first || create(:store) }

    trait :unaccessible do
      status { "unaccessible" }
      # 创建一个带指定属性的新Store关联
      store { create(:store, status: "closed", hours_before_open: 2) }
      # 若无需持久化到数据库,可改用build
      # store { build(:store, status: "closed", hours_before_open: 2) }
    end
  end
end

方式2:复用关联对象的Trait

如果Store工厂本身定义了对应属性的trait(比如:closed),可以直接复用该trait来简化代码:

假设Store工厂定义如下:

FactoryBot.define do
  factory :store do
    status { "open" }
    hours_before_open { 0 }

    trait :closed do
      status { "closed" }
      hours_before_open { 2 }
    end
  end
end

那么Fruit的trait可以改写为:

trait :unaccessible do
  status { "unaccessible" }
  store { create(:store, :closed) }
end

方式3:修改已关联的对象属性

如果不想替换掉已有的Store关联,只是需要修改其属性,可以使用after(:build)或after(:create)回调:

trait :unaccessible do
  status { "unaccessible" }

  after(:build) do |fruit|
    # 若store未持久化,直接修改属性
    fruit.store.status = "closed"
    fruit.store.hours_before_open = 2
    # 若需要持久化修改,调用save(注意:若store是新建未保存的,需先save)
    # fruit.store.save
  end

  # 针对已创建到数据库的fruit,用after(:create)
  after(:create) do |fruit|
    fruit.store.update(status: "closed", hours_before_open: 2)
  end
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:27:25