FactoryGirl关联重复键错误

时间:2017-08-03 17:19:09

标签: ruby-on-rails rspec factory-bot

分配已存在的关联的正确方法是什么?

我正在尝试在用户和城市之间分配一个has_one关系,其中许多用户或其他实体(例如某个事件)可以使用同一个城市。

代码

FactoryGirl.define do
  factory :user do
    name  'john'

    trait :in_boston do
      association   :city, factory: :boston
    end
  end
end

错误

PG :: UniqueViolation:错误:重复的键值违反了唯一约束“city_pkey”,因为它试图在数据库中创建两次波士顿。

我想做的只是参考现有工厂,而不是创建一个新工厂。

我当前的工作(但不太理想)解决方案

FactoryGirl.define do
  factory :user do
    name  'john'

    trait :in_boston do
      after(:create) do |user|
        user.city = City.find_by_name('Boston') || create(:boston)
      end
    end
  end
end

任何指导都将不胜感激,谢谢。

2 个答案:

答案 0 :(得分:1)

所以,我将假设您的模型代码是黄金的,并向您展示我如何设置测试。我不确定为什么你需要工厂根据城市是否存在来拥有决策权。只需在自己的工厂中实例化城市,并在测试设置中调用该关联。

工厂

# factories/cities.rb
FactoryGirl.define do
  factory :city do
    name  'Boston'
  end
end

# factories/users.rb
FactoryGirl.define do
  factory :user do
    name  'john'
    city
  end
end

测试

describe 'blah' do
  let( :city ){ create :city }
  let( :user ){ create :user, city: city }

  it 'user should have a city' do
    expect( user.city.name ).to eq 'Boston'
  end
end

答案 1 :(得分:0)

当回调创建该关联时,测试属于另一个模型的模型时,我遇到了相同的问题。

为了简单地说明,假设我有一个Book模型和一个Page模型,其中有Page belongs_to Book,并且有一个在创建图书时创建Page的回调

在我的工厂Page中,我尝试与Book关联,但是这样做一次,我创建了一本书,而页面的创建本身又在创建了同一本书。根据UniqueIndex条件,PostgreSQL失败。

在这种情况下,最简单的解决方案是在测试Page模型时不创建Page,而是简单地create(:book)然后使用book.page