Ошибка уникального ограничения FactoryBot при указании идентификатора на фабрике - PullRequest
0 голосов
/ 23 апреля 2020

Когда создается запись с указанным идентификатором, последующий вызов create завершается неудачно с уникальной ошибкой нарушения ограничения.

Output:

[1]> create(:user, id: 1)
=> #<User:0x00005615116f7378id: 1,created_at: Thu, 23 Apr 2020 08:21:04 CEST +02:00,updated_at: Thu, 23 Apr 2020 08:21:04 CEST +02:00...

[2]> create(:user)
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "users_pkey"DETAIL:  Key (id)=(1) already exists.

Я бы ожидал, что FactoryBot выберет последний созданный идентификатор и продолжит создание. :) Что мне здесь не хватает? Пожалуйста, порекомендуйте.

Версия FactoryBot (взята из Gemfile):
factory_bot_rails (5.1.1)
factory_bot (5.1.2)

[редактировать]

spec /factories/users.rb

FactoryBot.define do
  factory :user do
    first_name { "Max" }
    last_name { "Mustermann" }
    email_addresses { build_list(:email_address, 1) }
    password { TEST_USER_PASSWORD }
    accepted_terms_of_use { true }
  end
end

из базы данных / schema.rb

create_table "users", id: :serial, force: :cascade do |t|
  t.string "first_name", limit: 255
  t.string "last_name", limit: 255
  t.string "password_digest", limit: 255
  t.boolean "accepted_terms_of_use", default: false, null: false
end

add_foreign_key "email_addresses", "users"

1 Ответ

1 голос
/ 23 апреля 2020

Я бы ожидал, что FactoryBot выберет последний созданный идентификатор и продолжит создание. :) Что мне здесь не хватает?

Последовательности идентификаторов передаются базой данных, а не FactoryBot. FactoryBot назначает идентификаторы только тогда, когда вы используете build_stubbed для фальсификации постоянства.

Решение действительно простое - не используйте идентификаторы с жестким кодом. Вместо этого назначьте ваши фабрики для let / variable и ссылайтесь на них.

Bad:

let(:user) { create(:user, id: 1) }

it "does something" do
  get "/users/1"
end

Good:

let(:user) { create(:user) }

it "does something" do
  get user_path(user)
end
...