6

Ich habe ein Ereignismodell. Jedes Ereignis kann mehrere Sitzungen haben.Schienen, die bestätigen, dass eine Has Many-Beziehung mindestens 1 Eintrag hat

Ich möchte sicherstellen, dass kein Modell existieren kann, ohne dass ihm mindestens eine Sitzung zugeordnet ist.

validates :sessions, :length => { :minimum => 1 } 

Das Problem ist - wenn ich gehe, um zu versuchen, Sitzungen auf einem bestimmten Ereignis zu erstellen, indem Sie mein Modell-Methode aufrufen:

create_sessions() 

Was tut so etwas wie:

sessions.create(event_id: id,date: x,day_of_the_week:x.strftime("%A"),classPin: pin) 

für jede der Termine wird die Veranstaltung laufen.

Es schlägt mit dem Fehler zu speichern:

ActiveRecord::RecordNotSaved in EventsController#create 
You cannot call create unless the parent is saved 

Natürlich - von diesem Punkt der neue Ereignisaufzeichnung noch nicht gespeichert wurde - so dieser Verein noch nicht erstellt wird durch auf einer Vereinigung nicht zur Verfügung erstellen bis der Elternteil gespeichert ist!

Wie funktioniert eine Validierung zwischen dieser Art von Beziehung - weil die Validierung zum Zeitpunkt der Speicherung erfolgt .... aber ich möchte die Anzahl der Sitzungen validieren größer als 0 sein, bevor wir das Ereignis speichern!

Antwort

2

Ich denke, ein einfacher Weg wäre, Ihre Veranstaltungen und Sitzungen mit new statt create erstellen es wird nur die Objekte erstellen, aber nicht in der Datenbank speichern. Und nachdem Sie Ihre Sitzungen erstellt haben, machen Sie eine save auf Ihrer Veranstaltung.

@event = event.new(event_args) 
@event.sessions.new(session_args) 
@event.save 

Zusatz
Die @event.save speichert die @event Objekt und alle zugehörigen session Objekte. Ohne weitere Konfiguration werden nur neue Objekte gespeichert, siehe Active Record Autosave Association für weitere Informationen.

+0

Wird die Sitzungsvalidierung auch während der Ereignisspeicherung durchgeführt? – RenegadeAndy

+1

Die Sitzungen werden nicht standardmäßig auf 'save' überprüft. Sie müssen' validates_associated: sessions' hinzufügen. Weitere Informationen finden Sie im [Rails Validation Guide] (http://guides.rubyonrails.org/active_record_validations.html#validates-associated). –

+0

Funktioniert das? Wann werden die Sitzungen gespeichert? – tompave

2

Der Hauptpunkt ist, dass Ihre Validierung mit der Funktionsweise von ActiveRecord in Konflikt steht. Sie schaffen ein Paradoxon.

Es gibt eine Reihe von Lösungen, aber Sie müssen die Validierung entspannen. Das heißt, es sollte nicht ausgeführt werden, wenn der Datensatz neu ist.

können Sie entweder definieren es wie folgt aus:

class Event < ActiveRecord::Base 
    validates :sessions, length: { minimum: 1 }, 
         unless: :new_record? 
end 

Oder noch mehr Flexibilität haben, können Sie eine benutzerdefinierte Validierung verwenden:

class Event < ActiveRecord::Base 
    validate :session_count_validation 

    private 

    def session_count_validation 
    if !new_record? && sessions.count < 1 
     errors.add(:base, "Not enough sessions!") 
    end 
    end 
end 

Diese zweite Art hat auch den Vorteil, mehr performant: sessions.count wird einfach zählen, wie viele zugehörige Session Datensätze existieren, während Ihre ursprüngliche Validierung wird laden alle von ihnen im Speicher, und überprüfen Sie die Länge der Beziehung/arra y.

Dann, um sicherzustellen, dass Ihre Kreation Logik Sound ist, sollten Sie einen transaction verwenden:

begin 
    ActiveRecord::Base.transaction do 
    event = Event.create!(args) 

    sessions = dates.map do |date| 
     event.sessions.build(event_id: id, 
           date: date, 
        day_of_the_week: date.strftime("%A"), 
          classPin: pin) 
    end 

    sessions.each(&:save!) 
    end 
rescue 
    # your rescue logic 
    # e.g. display an error to the User 
end 

So wird, dass alles sicher zurück gerollt werden, wenn ein save! Vorgang fehlschlägt.

Verwandte Themen