ruby-on-rails 我怎样才能创建一个对象里面的其他对象?

n1bvdmb6  于 2023-02-26  发布在  Ruby
关注(0)|答案(2)|浏览(145)

我想创建一个“帖子”和一个“卡片”,但要创建卡片,必须具有company_id

factory :post do
  first_title { Faker::Name.name }
  sub_title { Faker::Name.name }
  email { Faker::Internet.email }
  company_id {}
  card { FactoryBot.create(:card, company_id: company_id) }
end

但我得到这个错误:

undefined local variable or method `company_id' for #<FactoryBot::SyntaxRunner:0x00007f629fb1b260
vc9ivgsu

vc9ivgsu1#

理想情况下,如果您的测试需要为自己创建一个定义良好的ocntext,而不依赖于工厂行为,那么您应该调用工厂,并将关联对象作为每个工厂调用的参数传递。
但是如果你真的想使用id来实现这个目标,你可以使用transient属性。
使用card对象:

factory :company do
  # whatever you need here
end

factory :card do
  company
end

factory :post do
  first_title { Faker::Name.name }
  sub_title { Faker::Name.name }
  email { Faker::Internet.email }
  card
end

let(:company) { FactoryBot.create :company }
let(:card) { FactoryBot.create(:card, company: company) }
let!(:post) { FactoryBot.create(:post, card: card) }

使用 transient 属性:

# factory:
factory :post do
  first_title { Faker::Name.name }
  sub_title { Faker::Name.name }
  email { Faker::Internet.email }

  transient do
    company_id { FactoryBot.create(:company).id }
  end

  after(:build) do |post, evaluator|
    card = FactoryBot.create(:card, company_id: evaluator.company_id)
    post.card = card
  end
end
# spec:
let(:company) { FactoryBot.create :company }
let!(:post) { FactoryBot.create(:post, company_id: company.id) }

更新:我为第一个示例中的工厂添加了代码

x0fgdtte

x0fgdtte2#

我过去很少使用FactoryBot,但是当我查看文档时,我会尝试这样做:

factory :post do
  first_title { Faker::Name.name }
  sub_title { Faker::Name.name }
  email { Faker::Internet.email }

  company
  card { association :card, country: country }
end

或者你可以在你的Card模型中添加一个回调函数来自动地将country设置为相关帖子的国家,如下所示:

# in app/models/card.rb
before_validation :set_country

private

def set_country
  self.country = post&.country
end

相关问题