首页 > 解决方案 > 在 Rails 中与 FactoryBot/Factory Girl 建立关联

问题描述

我有三个相互关联的工厂:Country该类有一个States 类,而theStates有一个City类。

国家.rb

FactoryBot.define do
factory :country do
    name { Faker::Address.unique.country }
  end
end

状态.rb

FactoryBot.define do
factory :state do
    association :country
    name { Faker::Address.state }
  end
end

城市.rb

   FactoryBot.define do
    factory :city do
        association :state
        name { Faker::Address.city }
      end
    end

在我的规范中,我想实例化特定的对象。

  before(:each) do
    create(:city, name:"Buffalo")
    create(:state, name:"New York")
    create(:country, name:"United States")

  end

我如何将美国国家与纽约州联系起来,将纽约州与布法罗市联系起来?

标签: rspecfactory-bot

解决方案


您可以将每个对象作为另一个工厂的属性传递。

before(:each) do
  country = create(:country, name:"United States")
  state = create(:state, name:"New York", country: country)
  create(:city, name:"Buffalo", state: state)
end

但这使您无法访问这些测试对象。相反,let!对每个对象使用 a。

let!(:country) { create(:country, name:"United States") }
let!(:state) { create(:state, name:"New York", country: country) }
let!(:city) { create(:city, name:"Buffalo", state: state) }

现在您可以在示例中引用countrystatecity。除非您特别需要为测试创建对象,否则您应该使用let并允许按需创建它们。

最后,我们可以通过反转它来节省大量工作。创建一个城市,然后从城市中检索州,从州中检索国家。

let(:city) { create(:city) }
let(:state) { city.state }
let(:country) { state.country }

city.name您可以在测试中引用,而不是指定确切的名称。例如。

let(:city) { create(:city) }
let(:state) { city.state }
let(:country) { state.country }

describe '#find_city' do
  it 'finds a city by name' do
    expect( country.find_city(city.name) ).to eq city
  end
end

describe '#find_state' do
  it 'finds a state by name' do
    expect( country.find_state(state.name) ).to eq state
  end
end

推荐阅读