更改模型的主键属性时,Rails FactoryGirl 重复键值违反唯一约束

Jay*_*een 2 ruby-on-rails factory-bot

有什么想法我在这个测试中做错了什么吗?

require "rails_helper"

describe "Rep", type: :feature do
  scenario "has a Manager and a Region" do
    rep = FactoryGirl.create(:rep)
    expect(rep.boss.email).to eq("first.last@email.com")
    expect(rep.region.name).to eq("NAT")
  end
end
Run Code Online (Sandbox Code Playgroud)

给定 Region 的此类

class Region < ApplicationRecord
  self.primary_key = "lid"
  has_many :reps
end
Run Code Online (Sandbox Code Playgroud)

我已经更改了区域的主键来引用该列lid

FactoryGirl.define do
  factory :rep do
    lid 1
    email 'first.last@email.com'
    association :boss, strategy: :build
    association :region, factory: :region, strategy: :build
  end

  factory :boss, class: Rep do
    lid 2
    email 'rep.manager@email.com'
    manager true
    association :region, factory: :region, strategy: :build
  end
end
Run Code Online (Sandbox Code Playgroud)

现在,当构建工厂中的关联时,region它会导致对该区域进行唯一性验证。

我使用来自另一个系统的称为旧版 id (lid) 的 id,并将它们用作主键(数据库迁移已设置为可以处理它们)。

我可以构建此应用程序独有的其他关联,因此具有标准的“id”字段

FactoryGirl.define do
  factory :region do
    lid 10
    name 'NAT'
  end
end
Run Code Online (Sandbox Code Playgroud)

我想要的只是repboss属于同一个region,所以当我建造一个rep工厂时,它会带有bossregion关联。

希望这只是一些我没有考虑的愚蠢的事情:confused:

rspec spec spec/features/reps/have_managers.rb
F

Failures:

  1) Reps belong to a manager
     Failure/Error: rep = FactoryGirl.create(:rep)

     ActiveRecord::RecordNotUnique:
       PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_regions_on_lid"
       DETAIL:  Key (lid)=(10) already exists.
       : INSERT INTO "regions" ("lid", "name", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "lid"
     # ./spec/features/reps/have_managers.rb:6:in `block (2 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # PG::UniqueViolation:
     #   ERROR:  duplicate key value violates unique constraint "index_regions_on_lid"
     #   DETAIL:  Key (lid)=(10) already exists.
     #   ./spec/features/reps/have_managers.rb:6:in `block (2 levels) in <top (required)>'
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经成功地关闭region_id null false flag并创建了 ,belongs_to optional这样我就可以注释掉区域关联并暂时忽略它

DBr*_*own 5

我确信您已经弄清楚了这一点,但为了涵盖这一点,您的工厂中发生了一些重叠的事情。由于老板是代表,因此您不希望将老板工厂与代表工厂关联起来,否则您最终会得到任何重叠的重复条目。相反,你可以考虑使用一个特质:

FactoryGirl.define do
  factory :rep, class: Rep do
    sequence(:lid) { |n| n }
    sequence(:email) { |e| "first.last#{e}@email.com" }
    association :region, factory: :region

    trait :boss do 
      manager true
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

然后,当您想要创建/构建这些时,您可以使用如下内容:

let(:rep) { create(:rep) }
let(:boss) { create(:rep, traits: [:boss]) }
Run Code Online (Sandbox Code Playgroud)