2017-10-26 2 views
1

So kann Contract viele Dienste haben. und die Join-Tabelle ist ContractsService (contracts_services), ziemlich einfach.RoR/Postgres - Fehler mit zwei Spalten eindeutigen Index. "Duplikatschlüsselwert verletzt eindeutige Einschränkung", auch ohne Datensätze

Index gesetzt mit:

def change 
    add_index :contracts_services, [:contract_id, :service_id], unique: true 
end 

Wenn ich versuche, so (oder über die API oder in irgendeiner Art und Weise, spezifisch so nicht auf dieses Stück Code) hinzuzufügen:

ContractsService.where(contract_id: 16, service_id: 17).first_or_create! 

ich bekomme diese Fehlermeldung:

ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_contracts_services_on_contract_id_and_service_id" 
DETAIL: Key (contract_id, service_id)=(16, 17) already exists. 

jedoch:

irb(main):015:0> ContractsService.where(contract_id: 16, service_id: 17).count 
D, [2017-10-26T07:25:01.782432 #4] DEBUG -- : (1.7ms) SELECT COUNT(*) FROM "contracts_services" WHERE "contracts_services"."deleted_at" IS NULL AND "contracts_services"."contract_id" = $1 AND "contracts_services"."service_id" = $2 [["contract_id", 16], ["service_id", 17]] 
=> 0 

Ich stecke hier, noch nie zuvor gesehen. Ich vermisse ich etwas Einfaches? oder ist der Index beschädigt? Etwas anderes?

+0

Hm, interessant. –

+0

@ FabrizioBertoglio Es ist kein Duplikat dieser Frage, mein Problem ist nicht mit Null-Indizes. –

Antwort

3

Scheint so, als hätten Sie default_scope in ContractsService Modell. Schauen Sie sich die SQL: "contracts_services"."deleted_at" IS NULL

Und Ihr eindeutiger Index enthält keine deleted_at Spalte.

Wenn Sie ContractsService.rewhere(contract_id: 16, service_id: 17).count versuchen wird, dann sollten Sie diesen Datensatz finden

+0

"Beachten Sie, dass wir im Gegensatz zur Nachbestellung nur die angegebenen Bedingungen aufheben - nicht die gesamte where-Anweisung." - 'rewhere' würde' deleted_at' nicht berühren. –

+0

Danke! Das ist es. 'acts_as_paranoid' deleted_at ist ein separater Index. Ich denke, ich sollte sie kombinieren, was ist der beste Weg, um diese zwei Spalten zu sagen, IF deleted_at ist NULL sonst die einzigartige Einschränkung zu ignorieren? –

+0

BTW Ich habe verwendet: 'ContractsService.only_deleted.where (Vertrags-ID: 16, Service-ID: 17) .count # => 1 ',' Rewhere' hat es nicht angezeigt. –

Verwandte Themen