42

Ich habe eine Release Modell mit medium und country Spalten (unter anderem). Es sollte nicht releases sein, die identische medium/country Kombinationen teilen.Schienen: validieren Eindeutigkeit von zwei Spalten (zusammen)

Wie würde ich dies als eine Schienenvalidierung schreiben?

validates_uniqueness_of :medium, scope: :country 

die documentation für einige weitere Beispiele siehe:

+6

Mögliches Duplikat [Rails: Eindeutigkeit von mehreren Spalten Validieren] (http://stackoverflow.com/questions/4870961/rails-validate-uniqueness-of-multiple-columns) – Khoga

Antwort

78

Sie können eine uniqueness Validierung mit der Option scope verwenden.

Außerdem sollten Sie einen eindeutigen Index für die DB hinzufügen aus vorbei an den Validierungen neue Datensätze zu verhindern, wenn zur gleichen Zeit überprüft, bevor geschrieben:

class AddUniqueIndexToReleases < ActiveRecord::Migration 
    def change 
    add_index :releases, [:country, :medium], unique: true 
    end 
end 



class Release < ActiveRecord::Base 
    validates :country, uniqueness: { scope: :medium } 
end 
+0

+1 für den Index, aber -1 für das 'unique', da es nicht erkannt wird. Für diesen Teil habe ich die Antwort unten verwendet. – Aleks

+2

Ja, Entschuldigung, der Validierungsschlüssel sollte "Eindeutigkeit", nicht "einzigartig" sein. Siehe die verknüpfte Dokumentation. Repariere die Antwort. – tompave

+1

Hm, schön, danke :) Um mich zu wiederholen - das Setzen des Index bringt die Lösung auf die nächste Ebene, und nicht nur wie andere "Kodierung" -Lösungen, denen ich begegnet bin, bevor diese Antwort gefunden. +1 dafür – Aleks

17

Sie können einen :scope Parameter auf Ihren Validator wie diese passieren.

+1

Einfach, klar, und es funktioniert. Vielen Dank! –

+2

@DennisBest Es "funktioniert", aber es schützt nicht vor Rennbedingungen. Wenn zwei Clients gleichzeitig Anfragen stellen, können sie beide die Validierung bestehen, wenn keine der Daten an die Datenbank übergeben wird, bevor die andere validiert wird. Sie benötigen auch eine eindeutige Datenbankeinschränkung wie in tompaves Antwort. – soupdog

14

Alle oben genannten Antworten fehlen, wie die Validierung Eindeutigkeit mehrerer Attribute in einem Modell. Im folgenden Code wird erläutert, wie mehrere Attribute in einem Bereich verwendet werden.

validates :country, uniqueness: { scope: [:medium, :another_medium] } 

Es bestätigt die Einzigartigkeit von country in allen Zeilen mit Werten von medium und another_medium.

Hinweis: Vergessen Sie nicht, einen Index zu der obigen Spalte hinzuzufügen, dies sichert einen schnellen Abruf und fügt eine DB-Level-Validierung für eindeutige Datensätze hinzu.