如何在工厂机器人rails的after_build中创建关联?

问题描述 投票:0回答:2

我有一个数据模型,其中

account
在子域上具有唯一的验证。

我的大多数其他对象都与

account
对象相关联。

在我的数据模型中,

product
有一个
account_id
和一个
program_id

在 FactoryBot 中我想写一些类似的东西:

create(:product, :with_program, account: account)

然后使用该特定帐户创建所有关联的资源。

在我的

product
工厂:

FactoryBot.define do
  factory :product do
    association :account
    association :program
    trait :with_program do
      after_build do |product|
        product.program = create(
          :program,
          :with_author,
          account: product.account
        )
      end
    end
  end
end

然而,这会直接创建程序,该程序又会重新创建帐户,并触发帐户的唯一性验证。

FactoryBot.define do
  factory :program do
    association :account
  end
end

到目前为止,我发现的唯一解决方案是在创建实际产品之前创建产品所依赖的所有关联并将其传递给

create method
:

  let(:program) do
      create(
        :program,
        :with_future_start_date_sessions,
        account: account,
        author: author
      )
    end
create(
        :product,
        :draft,
        program: program,
        account: account
      )
    end

有没有更聪明的方法将

account
传递给所有
product
关联并在
trait
或类似的东西中创建它们?

ruby-on-rails rspec associations factory-bot
2个回答
3
投票

在创建复杂的关联时,我总是喜欢采用自上而下的方法。不要使用帐户创建产品,而是尝试使用产品创建帐户,这样您就不需要事先创建关联。

FactoryBot.define do
  factory :account do
    # account attributes...

    trait :with_products do
      transient do
         product_count {2}
      end

      after(:build, :create) do |account, evaluator|
         create_list(
           :product,
           evaluator.product_count, 
           :with_program, 
           account: account
         )
      end
    end
  end
end

然后您可以通过调用来创建产品

# 1 account, 5 products
FactoryBot::create(:account, :with_products, product_count: 5)
# 5 accounts with 1 product each
FactoryBot::create_list(:account, 5, :with_products, product_count: 1)

0
投票

我不确定这是否有帮助,但我做了这样的事情。我对相关模型进行了各种验证,这样构建和创建工厂都有效:

FactoryBot.define do
  factory :product do
    account(:build) do |product|
      product.program ||= build(:program)
      product.account ||= build(:account)
    end

    after(:create) do |product|
      product.program.save!
      product.account.save!
    end
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.