Validieren verschachtelte Modelle?
-
05-07-2019 - |
Frage
Um genauer zu sein, "Wie kann ich bestätigen, dass ein Modell mindestens x gültig zugehörige Modelle erfordert geschaffen werden?" . Ich habe versucht, verschachtelte Modelle zu validieren, die als Mutter in der gleichen Form erstellt bekommen (und zeigen schließlich sofort Validierungen a la jQuery). Als beliebtes Beispiel kann die folgenden Modelle und Schema übernehmen.
class Project
include DataMapper::Resource
property :id, Serial
property :title, String, :nullable => false
has 2..n, :tasks
end
class Task
include DataMapper::Resource
property :id, Serial
property :project_id, Integer, :key => true
property :title, String, :nullable => false
belongs_to :project
end
Alle Validierungen sind in den Schemadefinitionen erfolgen, wie Sie sehen können. Das wichtige ist hier „has 2..n, :tasks
“. Diese Validierung tatsächlich funktioniert normalerweise gegeben, dass die verschachtelte Task-Attribute im params-Hash produzieren gültig Aufgaben. Wenn sie produzieren eine ungültig Aufgabe, aber dann wird nicht die Aufgabe bekommen erstellt und Sie werden mit einem Projekt am Ende, die weniger als zwei Aufgaben hat, und damit eine ungültig Projektobjekt.
Wie ich es verstehe, ist dies, weil es nicht herausfinden kann, wenn die Aufgabe Attribute gültig sind oder nicht, bis sie die Aufgaben zu retten versucht, und da - soweit ich weiß - die Aufgaben können nicht vor dem Projekt gerettet werden, ist das Projekt nicht bewusst, wenn die Aufgaben gültig sind oder nicht. Bin ich richtig in der Annahme, dies?
Wie auch immer, ich hatte gehofft, es würde eine schnelle Antwort, aber es scheint viel weniger trivial dann hatte ich gehofft. Wenn Sie Vorschläge haben überhaupt, das würde sehr geschätzt werden.
Lösung
Ich fand eine schöne Lösung, die hier über die Transaktionen in DataMapper. Grundsätzlich ist dieser Transaktion versucht, das übergeordnete Objekt sowie alle untergeordneten Objekte zu speichern. Sobald man speichern ausfällt, dann wird die Transaktion beendet und nichts geschaffen wird. Wenn alles gut geht, werden die Objekte erfolgreich speichern.
class Project
def make
transaction do |trans|
trans.rollback unless save
tasks.each do |task|
unless task.save
trans.rollback
break
end
end
end
end
end
Dies stellt sicher, dass alles, was gültig ist, bevor es alles gespeichert wird. Ich brauche nur zu meinen #save und #update Methoden ändern in meinem Controller-Code #make.
Andere Tipps
SET CONSTRAINTS ABGEGRENZTE könnte nützlich sein, wenn die Datenbank-Engine, die unterstützt wird.
Ansonsten schreibe vielleicht eine gespeicherte Prozedur, die Einsätze zu tun, und dann sagen, dass es das resonsibility der gespeicherten Prozedur, um sicherzustellen, dass nur korrekte, validierten Daten eingefügt wird.
Es ist ein Modell, Methode valid?
, die Validierungen auf einem Modellobjekt ausgeführt wird, bevor es gespeichert wird. So ist die einfache Möglichkeit, die Assoziationen zu validieren wäre validates_with_block' or 'validates_with_method
zu verwenden, um die Validierungen auf den Verbänden zu überprüfen.
Es wäre etwa so aussehen
validates_with_block do
if @tasks.all?{|t|t.valid?}
true
else
[false, "you have an invalid task"]
end
end
Oder Sie könnten sehen dm-Verband-Validator oder dm-akzeptiert-nested-Attribute
Edit: für zusätzliche verrückt. laufen Validierungen auf die Aufgaben, dann überprüfen, um zu sehen, ob die Fehler nur diejenigen zur Vereinigung in Zusammenhang stehen.
validates_with_block do
if @tasks.all?{|t|t.valid?;!t.errors.any?{|e|e[0]==:project}}
true
else
[false, "you have an invalid task"]
end
end