So überprüfen Sie ein nested-Modell-Objekt basierend auf den Zustand des übergeordneten Objektes?
Schreibe ich einen Assistenten in form Schienen; z.B. mehrere Eingabe-Seiten für ein Modell-Objekt.
Die Grundlagen meines Ansatzes sind beschrieben in Ryan Bates' Multistep-Formular railscast : http://railscasts.com/episodes/217-multistep-forms (falls jemand wissen möchte, WARUM hinter den code unten).
Objekte unter Kontrolle sind hier "Teilnehmer", die eine "Adresse"
Mein problem ist, dass ich nur überprüft werden soll das verschachtelte Objekt (Adresse), wenn der Benutzer versucht, den Fortschritt der Vergangenheit der Adresseingabe-Bildschirm. Dies ist derzeit verfolgt, das über ein Attribut auf dem Teilnehmer-Modell namens "current_step"
So, ich habe eine Frage:
class Participant < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
validates_presence_of :first_name, :last_name, :if => self.current_step == "name"
...
def steps = %w[ name address confirm ] # the steps the wizard will follow
end
Adresse:
class Address < ActiveRecord::Base
belongs_to :participant
validates_presence_of :address1, :state, :suburb, :postcode #, :if => participant.current_step == "address"
end
Das Prinzip dieses Ansatzes ist der "create" - action wird aufgerufen, auf dem controller (nicht gezeigt) für jeden Schritt des Assistenten, und es validiert nur eine Teilmenge des Modells bei jedem Schritt verarbeitet wird.
Derzeit, wenn ich den ersten Bildschirm ("name") und versuchen Sie es und gehen Sie auf die Adresse Schritt, die Adresse Validierung wird immer ausgelöst, und ich komme zurück an den "name" - Bildschirm mit der Validierung Fehler für leeres Adresse details.
Also habe ich versucht eine Reihe von Ansätzen hier, der Letzte Teil davon war die auskommentiert Zustand auf der Adresse-Validierung, die oben gezeigt - dieses, das ich gefunden habe, funktioniert nicht so ich bin nur Gebäude Teilnehmer->Adresse Objekten, aber nicht speichern. Daher @participant.address
bekommt von mir die Adresse-Objekt, aber @participant.address.participant
null ist als Adresse noch nicht haben ein participant_id foreign key lookup Eltern werden.
Den Grund für meine Kämpfe zu sein scheint, die Aufnahme von der super-praktisch accepts_nested_attributes_for
Methode. Ich hatte erwartet, zu verwenden validates_associated
zu tun, die Validierung, aber ich sehe, dass die accepts_nested_attributes_for
tag beide überträgt die Parameter form, schön zum erstellen von verschachtelten model-Objekte, sondern sorgt auch für die participant#valid?
- Methode ruft nach unten auf die Adresse, die Validierung in ALLEN Situationen.
Also mein dilemma ist, wie am besten die participant#valid?
Methode, um gültig die teilweise vollständige Modell, basierend auf der current_step
parameter in den Teilnehmer ?
BEARBEITEN - Aktualisierung entfernen Sie zusätzliche info, und destillieren nach unten, um den Kern des Problems
- Nur eine Vermutung, aber haben Sie versucht, überprüft,: Adresse, :if => Proc.new {|Teilnehmer| Teilnehmer.current_step == 'name' }
- Eines der ersten Dinge, die ich versucht - aber wie oben erwähnt (vielleicht nicht allzu deutlich, das gebe ich zu) das Adresse-Objekt hat kein Teilnehmer, bis es gespeichert, sodass ich immer einen Fehler beim Aufruf current_step auf eine null-Klasse.
- Hinzufügen :inverse_of, um Ihre Beziehungen, so das Adresse-Objekt wird eine Referenz auf seine Teilnehmer, wenn es gebaut wird.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Fügen Sie ein virtuelles Attribut auf Ihre
Address
Modell:Legen Sie die virtual-Attribut für die Adresse-Objekt aus, wenn
current_step
eingestellt ist.skip_validation
und verwenden Sie ein:unless
statt:if
, so der Standard ist, zu validieren. Funktioniert Super so weit.skip_validation
ist, dass Sie nicht wirklich wissen, warum es verwendet wird. Ich bin gekommen, über code, wo ich konnte ' T es herausfinden und die dev, die es schrieb, hatte ich vergessen. :*(Nur die Zuordnung im controller bevor Sie anrufen
participant.valid?
:Obwohl die ActiveRecord - "validieren" - Methoden sind sehr bequem, es gibt nichts zu verhindern, dass Sie "Ihre eigenen Rollen", vielleicht mit
before_save
Haken. Sie ersetzen könnte Ihrvalidates_presence_of
validator aufAddress
mit einembefore_save
Haken, die nicht-Validierung nur unter bestimmten Bedingungen. Dannaccepts_nested_attributes_for
vermutlich würde es nicht sehen.