Schienen 4 - Starke Parameter - Verschachtelte Objekte


144

Ich habe eine ziemlich einfache Frage. Aber noch keine Lösung gefunden.

Hier ist die JSON-Zeichenfolge, die ich an den Server sende:

{
  "name" : "abc",
  "groundtruth" : {
    "type" : "Point",
    "coordinates" : [ 2.4, 6 ]
  }
}

Mit der neuen Genehmigungsmethode habe ich:

params.require(:measurement).permit(:name, :groundtruth)

Dies wirft keine Fehler aus, aber der erstellte Datenbankeintrag enthält null anstelle des Grundwahrheitswerts.

Wenn ich nur setze:

params.require(:measurement).permit!

Alles wird wie erwartet gespeichert, aber dies beeinträchtigt natürlich die Sicherheit, die durch starke Parameter bereitgestellt wird.

Ich habe Lösungen gefunden, wie man Arrays zulässt, aber kein einziges Beispiel mit verschachtelten Objekten. Dies muss irgendwie möglich sein, da es ein ziemlich häufiger Anwendungsfall sein sollte. Wie funktioniert es?



1
@vinodadhikary Es war richtig ... Ich denke, das OP ist verwirrt. So seltsam es auch klingen mag, wenn Sie verschachtelte Attribute zulassen möchten, geben Sie die Attribute des verschachtelten Objekts innerhalb des Arrays an. Wenn Sie jedoch mehrere Objekte verschachteln möchten, wickeln Sie sie in einen Hash ein. Siehe api.rubyonrails.org/classes/ActionController/… und github.com/rails/rails/blob/master/actionpack/lib/…
j03w

@ j03w, Danke für den Link zur Quelle. Es ist jetzt klar. Sie sollten hier eine Antwort auf diesen Befund hinzufügen, da ich denke, dass dies vielen anderen Menschen helfen wird.
Vee

Antworten:


181

So seltsam es auch klingen mag, wenn Sie verschachtelte Attribute zulassen möchten, geben Sie die Attribute des verschachtelten Objekts in einem Array an. In deinem Fall wäre es

Update wie von @RafaelOliveira vorgeschlagen

params.require(:measurement)
      .permit(:name, :groundtruth => [:type, :coordinates => []])

Wenn Sie jedoch mehrere Objekte verschachteln möchten, wickeln Sie sie in einen Hash ein

params.require(:foo).permit(:bar, {:baz => [:x, :y]})


Rails haben tatsächlich eine ziemlich gute Dokumentation dazu: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit

Weitere Erläuterungen finden Sie in der Implementierung von permitund strong_parametersselbst: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247


5
Beide Fälle sind in dieser Antwort gleich. Tatsächlich sind die geschweiften Klammern um {: groundtruth => [...]} optional. Es ist ein Hash, aber der Interpreter kann ohne explizite geschweifte Klammern bestimmen, wo der Hash beginnt und endet.
sprechender

Verschachtelte Arrays von Attributen erlauben keine verschachtelten Attribute. Verschachtelte Attribute und attr_accessor werden in meiner Anwendung als "Unzulässige Parameter" aufgeführt. Immer noch auf der Suche nach einer sicheren Lösung.
Katarzyna

Bei mehreren verschachtelten Objekten sollten Sie auch zulassen, dass die ID dafür funktioniert. Weitere Infos hier: stackoverflow.com/questions/18308714/…
Fabrice Carrega

1
Dies erlaubt nur EINEN Satz verschachtelter Attribute. Dies funktioniert bei einem zu vielen nicht.
AKWF

23

Ich fand diesen Vorschlag in meinem Fall nützlich:

  def product_params
    params.require(:product).permit(:name).tap do |whitelisted|
      whitelisted[:data] = params[:product][:data]
    end
  end

Überprüfen Sie diesen Link von Xaviers Kommentar zu Github.

Dieser Ansatz listet das gesamte Objekt params [: Messung] [: Grundwahrheit] auf.

Verwenden der ursprünglichen Fragenattribute:

  def product_params
    params.require(:measurement).permit(:name, :groundtruth).tap do |whitelisted|
      whitelisted[:groundtruth] = params[:measurement][:groundtruth]
    end
  end

4
Nur eine Randnotiz: Dies wird weiterhin im Protokoll als unzulässige Parameter angezeigt, aber das Modell akzeptiert sie trotzdem.
Weston Ganger

5
Ich bin mir von Rails 4 nicht sicher, aber in meinem Rails 5-Projekt muss ich anrufen permit!, um auf die Whitelist gesetzt zu werden. Andernfalls bleibt es nach dem Tippen unzulässig. In diesem Fall wäre esparams[:measurement][:groundtruth].permit!
nayiaw

@nayiaw Ich bekomme auch die unzulässige Nachricht, aber das Hinzufügen permit!löst diese Fehlererlaubnis aus NoMethodError (undefined method ! ' für # <Array: 0x007f80cb71ea00>): `
wuliwong

Die @ wuliwong- permit!Methode ist in nicht verfügbar Array. Sie müssen Zugriff auf die jeweilige Klasseninstanz haben, um Zugriff zu haben permit!(es ist eine Weile her, daher habe ich den Klassennamen vergessen, aber er ActionController::Parametersbasiert auf dieser Seite ).
Nayiaw

8

Zulassen eines verschachtelten Objekts:

params.permit( {:school => [:id , :name]}, 
               {:student => [:id, 
                            :name, 
                            :address, 
                            :city]},
                {:records => [:marks, :subject]})

0

Wenn es sich um Rails 5 handelt, params.permit(:name, groundtruth: [:type, coordinates:[]])funktioniert es aufgrund der neuen Hash-Notation einwandfrei.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.