如何在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
相关产品推荐
相关产品推荐

