Sie können eine Spalte validates
validieren uniqueness
:
validates :user_id, uniqueness: {scope: :friend_id}
Die Syntax für die Validierung mehrerer Spalten ist ähnlich, Sie sollten jedoch stattdessen ein Array von Feldern angeben:
validates :attr, uniqueness: {scope: [:attr1, ... , :attrn]}
Die oben gezeigten Validierungsansätze haben jedoch eine Rennbedingung und können keine Konsistenz gewährleisten. Betrachten Sie das folgende Beispiel:
Datenbanktabellendatensätze sollen durch n Felder eindeutig sein ;
Mehrere ( zwei oder mehr ) gleichzeitige Anforderungen, die jeweils von separaten Prozessen verarbeitet werden ( Anwendungsserver, Hintergrundarbeitsserver oder was auch immer Sie verwenden ), greifen auf die Datenbank zu, um denselben Datensatz in die Tabelle einzufügen.
Jeder parallele Prozess überprüft, ob ein Datensatz mit denselben n Feldern vorhanden ist.
Die Validierung für jede Anforderung wird erfolgreich bestanden, und jeder Prozess erstellt einen Datensatz in der Tabelle mit denselben Daten.
Um diese Art von Verhalten zu vermeiden, sollte der Datenbank-Tabelle eine eindeutige Einschränkung hinzugefügt werden . Sie können es mit dem add_index
Helfer für ein (oder mehrere) Felder festlegen, indem Sie die folgende Migration ausführen:
class AddUniqueConstraints < ActiveRecord::Migration
def change
add_index :table_name, [:field1, ... , :fieldn], unique: true
end
end
Vorsichtsmaßnahme : Selbst nachdem Sie eine eindeutige Einschränkung festgelegt haben, versuchen zwei oder mehr gleichzeitige Anforderungen, dieselben Daten in db zu schreiben. Anstatt jedoch doppelte Datensätze zu erstellen, wird eine ActiveRecord::RecordNotUnique
Ausnahme ausgelöst, die Sie separat behandeln sollten:
begin
# writing to database
rescue ActiveRecord::RecordNotUnique => e
# handling the case when record already exists
end