Ruby on Rails: Wie können verschachtelte Attribute unter bestimmten Bedingungen überprüft werden?

8

Ich habe diese Modelle:

%Vor%

... und diese Ansichten:

_fields.html.erb :

%Vor%

_address.html.erb:

%Vor%

people_controller.rb :

%Vor%

In meinem Person -Modell muss sichergestellt werden, dass nur wenn die organisation_id einer Person leer ist, die Adressfelder dieser Person vorhanden sein müssen.

Ich habe so etwas versucht:

%Vor%

Aber es funktioniert nicht.

Wie kann das gemacht werden?

Danke für jede Hilfe.

    
Tintin81 07.10.2012, 15:14
quelle

2 Antworten

24

Zunächst möchte ich sicher sein, dass Sie blank? und nicht present? meinen. Normalerweise sehe ich das:

%Vor%

Das bedeutet, dass Sie die Adresse nur validieren möchten, wenn auch eine Organisation vorhanden ist.

Betreffend, :accepts_nested_attributes_for , verwenden Sie diese Funktion, indem Sie verschachtelte Formularattribute oder ähnliches übergeben? Ich möchte nur sicherstellen, dass Sie diese Funktionalität unbedingt verwenden müssen. Wenn Sie sich nicht mit geschachtelten Formularattributen beschäftigen, können Sie die kaskadierende Validierung mithilfe von:

implementieren %Vor%

Wenn Sie :accepts_nested_attributes verwenden müssen, überprüfen Sie den Parameter :reject_if . Grundsätzlich können Sie das Hinzufügen eines Attributs (und seiner Nachkommen) ablehnen, wenn bestimmte Bedingungen zutreffen:

%Vor%

Wenn nun keines der obigen Beispiele zutrifft, werfen wir einen Blick auf Ihre Syntax:

Es sollte funktionieren, :if/:unless nimm Symbole, Zeichenfolgen und Prozeduren . Sie müssen nicht auf den foreign_key zeigen, sondern können vereinfachen, indem Sie auf Folgendes zeigen:

%Vor%

Sie haben andere Validierungen im Adressmodell, richtig? Wird die Adresse validiert, wenn Sie es nicht möchten? Oder wird die Adresse nicht validiert? Ich kann Ihnen helfen, es in der Konsole zu testen, wenn Sie mir einige zusätzliche Details geben können.

  1. Um mir die Sache zu erleichtern, habe ich die rails config geändert: config.active_record.whitelist_attributes = false
  2. Ich habe einen Grundstein für dich erstellt
  3. Ich habe auch ein Beispielprojekt. Lassen Sie mich wissen, wenn Sie interessiert sind.

    Grundlegende Punkte:

  4. Folgendes zu Person hinzugefügt, um sicherzustellen, dass entweder Org oder Adresse gültig sind:

    validates_presence_of :organisation, :unless => "address.present?" validates_associated :address, :unless => "organisation.present?"

  5. Validierung zu Address hinzugefügt, um Fehler auszulösen, wenn Org nicht vorhanden ist: validates_presence_of :line1, :line2, :city, :zip

    Ich konnte die gewünschten Anforderungen erfüllen. Bitte schauen Sie sich in der von mir erstellten Liste an , wo ich einen vollständigen Testplan für die Konsole habe.

Ich habe eine Controller-Datei zum vorherigen gist hinzugefügt .

Übersicht:

  1. Alles, was Sie brauchen, um die Person zu erstellen, ist: %Code%
  2. : organization_id wird immer aus dem param-Knoten von: person wie folgt gefunden: %Code% Also bist du, wenn es nie wahr sein wird.

Ich habe den Hauptteil mit den notwendigen Änderungen an dem Controller aktualisiert, das Modell und das Formular .

Übersicht:

  1. Sie müssen Ihren Controller aufräumen. Sie verwenden @person = current_user.people.build(params[:person]) , also interessieren Sie in der: create nur für params[:person][:organisation_id] . Darüber hinaus müssen Sie in accepts_nested_attribute alle Instanzvariablen einrichten, die von der partiellen Instanz verwendet werden. Dies führt dazu, dass NICHT die Aktion params[:person] zurückgibt. Die Aktionen render :new und :new müssen ebenfalls vereinfacht werden.
  2. Ihr Personenmodell muss das :new -Argument verwenden, da die Adressfelder zurück zur: create-Aktion als :edit kommen. Sie möchten nur die Verknüpfung erstellen, wenn Werte vorhanden sind. Dann wird Ihre :reject_if für :address_attributes => {:line1 => '', :line2 => '', etc} gut funktionieren.
  3. Ihr Formular muss die Organisations-ID an den Controller und nicht an die Organisationsnamen

    übergeben

    Es ist alles in dem Kern

Sollte der letzte Kern sein.

Übersicht:

  1. Fügen Sie Ihrer Bearbeitungsaktion direkt nach dem Erstellen der @person Folgendes hinzu:

    @ person.build_address Wenn @ person.address.nil? Dies stellt sicher, dass Sie die Adresseingänge haben, auch wenn die @ person.address nicht existiert. Es existiert nicht wegen der: reject_if-Bedingung bei accept_nested_attributes

  2. Ich habe das: reject_if wie folgt getrocknet. Es ist ein bisschen hacky, aber hat etwas Nutzen:

    %Vor%

    a. validates_presence_of - & gt; das Ergebnis von params [: person] [: Adresse]
      b. :organisation - & gt; return alle Schlüssel-Werte mit Ausnahme von 'ID'
      c. attrs - & gt; Rückgabe aller Werte aus einem Hash als Array   d. .except('id') - & gt; Erfüllen alle Elemente in dem Array die folgende Überprüfung?   e. .values - & gt; Ruby-Kürzel für einen Block, wie folgt: .all?

Matt Dressel 07.10.2012, 19:52
quelle
0

Bist du sicher, dass du nicht meintest:

%Vor%     
varatis 07.10.2012 15:20
quelle