Skip to main content
Vorgestellt von Chris Oliver für GoRails. Erneut veröffentlicht auf AppSignal am 19. September 2026. ActionController::Parameters#with_defaults liefert Werte für Schlüssel, die nicht in der Anfrage enthalten waren. Es ist ein Alias für reverse_merge, sodass der Hash, den Sie übergeben, gegen alles verliert, was der Browser übermittelt hat. Es hat seine Berechtigung, weil der Browser in mehreren gewöhnlichen Fällen überhaupt nichts übermittelt. Ein Controller, der „nicht vorhanden“ und „false“ unterschiedlich behandelt, macht in diesen Fällen etwas falsch.

Was dieser Artikel behandelt

  • Standardwerte für Parameter festlegen, die der Browser möglicherweise auslässt.
  • Wie Rails-Checkboxen dies bereits mit einem verborgenen Feld lösen.
  • Warum ein Standardwert kein Autorisierungsmechanismus ist.

Anforderungen

Einen Standardwert festlegen

Wenn status ankommt, wird er verwendet. Wenn nicht, wird "draft" verwendet. Nicht markierte Checkboxen und nicht ausgewählte Mehrfachauswahl-Felder sind der übliche Grund, warum ein Schlüssel fehlt. Ein Standardwert ist übersichtlicher als eine Kette von Bedingungen in der Action. ActionController::Parameters ist kein Hash, obwohl es sich einige Mühe gibt, sich wie einer zu verhalten. Es implementiert merge, values_at, compact, blank? und eine lange Liste weiterer Methoden. with_defaults gehört zu dieser Oberfläche.

Was Rails-Checkboxen bereits tun

Bevor Sie bei einer Checkbox zu einem Standardwert greifen, beachten Sie, dass Rails dies in der Regel bereits übernimmt. Eine nicht markierte HTML-Checkbox übermittelt nichts, und ein Formular hat keine Möglichkeit auszudrücken, „dies wurde nicht markiert“. Deshalb rendert form.check_box zwei Eingabefelder: ein verborgenes Feld mit dem Wert 0 und die Checkbox selbst mit dem Wert 1. Wenn die Box markiert ist, werden beide in Dokumentreihenfolge übermittelt. Rails erhält 0, dann 1, und verwendet den letzten Wert. Ist sie nicht markiert, kommt nur die 0 an. Das Ergebnis ist, dass eine Rails-Checkbox immer etwas übermittelt und Sie selten einen Standardwert dafür benötigen.

Ein Standardwert ist keine Autorisierung

Standardwerte verlieren gegen übermittelte Werte. Das ist es, was sie zu Standardwerten macht. Ein Standardwert kann einen Nutzer also nicht davon abhalten, einen Wert zu setzen: Jeder, der den Schlüssel übermittelt, überschreibt ihn. Bei Attributen, die der Nutzer nicht kontrollieren darf, wie etwa den Autor eines Datensatzes, sollten Sie diese Absicht nicht als Standardwert ausdrücken:
Weisen Sie ihn auf dem Server zu, außerhalb der erlaubten Parameter:
user_id ist nicht erlaubt, kann also überhaupt nicht per Mass Assignment gesetzt werden. Die Zuordnung des Eigentümers kommt aus der Session und nicht aus der Anfrage. Verwenden Sie with_defaults für echte Standardwerte, bei denen es akzeptabel ist, dass ein Nutzer den Wert überschreibt.
Überprüfen Sie eine Anwendung einmal darauf. Ein erlaubtes Attribut mit einem Standardwert ist vom Nutzer kontrollierbar, egal was der Standardwert suggeriert. Eigentümer-, Rollen-, Preis- und Statusfelder gehören alle nicht in die Liste der erlaubten Parameter.

Sehen, was übermittelt wurde

Wenn sich ein Standardwert nicht wie erwartet verhält, lautet die Frage fast immer, was die Anfrage enthielt. Lokal können Sie das im Netzwerk-Panel ablesen. In der Produktion zeichnet AppSignal Request-Parameter bei Fehler- und Performance-Traces auf. Ein Issue zeigt dann die Parameter, die ihn tatsächlich verursacht haben, statt der Parameter, die Sie angenommen hatten. Da Parameter routinemäßig personenbezogene Daten enthalten, überprüfen Sie, was gesendet wird. AppSignal unterstützt das Filtern von Parametern, sodass sensible Schlüssel nie übertragen werden. Konfigurieren Sie dies, bevor Sie sich bei Issues auf Parameterdaten verlassen.

Transkript

Aus dem Video transkribiert und leicht bearbeitet. Die automatischen Untertitel haben mehrere Produkt- und API-Namen falsch verstanden, und diese wurden korrigiert.
0:02 Hey Leute, in dieser Episode geht es um Action-Controller-Parameter, und zwar speziell um die Methode hier unten, with defaults. Das ist einfach ein Alias für reverse merge, aber es ist eine der Sachen, die ich häufig sehe und selbst häufig in unseren Controllern mache, wenn ich einige Standardwerte zuweisen muss. Schauen wir uns also ein Beispiel an. Lassen wir ein Scaffold für ein Post-Modell generieren, und wir wollen, dass der Post zu einem Nutzer gehört. Außerdem soll der Post einen Titel und einen Body haben, der eine Text-Spalte ist.0:41 Also erstellen wir das. Wir führen rails db:migrate aus und öffnen das Ganze in unserem Editor, und unser Post-Controller hier wird das generieren. Der wichtige Teil ist aber, dass dieser neue Post tatsächlich einen Standardwert für diese user-Referenz zuweisen soll. Wir könnten hier also current user sagen und das einfach zuweisen. Aber richtig schön wäre es, wenn wir das als Teil der eingehenden Parameter machen könnten, und genau das können wir tun.1:12 Statt also diese Zeile hier in unserer create-Action ein bisschen komplizierter zu machen, können wir hier with defaults verwenden und sagen, dass user gleich current user ist. Ich habe jetzt keine current-user-Methode, also sagen wir dafür einfach user.first. Und wir wollen nicht, dass der Nutzer wählen kann, wer den Post geschrieben hat, also stellen wir sicher, dass die user ID hier nicht in den erlaubten Parametern ist. Wenn wir zu unserem Post-Formular gehen, können wir die user ID entfernen, und das wird im Grunde zuerst diesen Hash verwenden und dann alle title- und body-Felder einmergen, die in den Parametern ankamen. Man kann das auch für andere Dinge verwenden, zum Beispiel wenn man eine Checkbox oder ein Array oder Ähnliches hat, das vom Browser übermittelt werden kann oder nicht. Man kann hier seinen Standard-Hash an Parametern angeben, und diese können dann durch das überschrieben werden, was vom Browser übermittelt wird.2:11 Das ist also ein super cooles kleines Feature. Öffnen wir jetzt unseren Rails-Server und gehen zu slash posts slash new. Wir können test und test eingeben. Wenn wir diesen Post erstellen, bekommen wir hier wegen with defaults die user ID Nummer eins zugewiesen. Das ist also im Grunde einfach das reverse merge, das in einen Hash eingebaut ist, obwohl die Action-Controller-Parameter eigentlich nicht von einem Hash erben.2:41 Wenn wir dazu auf GitHub gehen, sehen wir, wenn wir uns die Implementierung davon ansehen, dass es all diese Methoden gibt, die zu Hashes passen, wie merge, values at, compact, blank, compact, was auch immer. Wir haben all diese Implementierungsdetails, die dafür sorgen, dass sich das in den meisten Fällen wie ein Hash verhält. Aber wenn wir wieder nach oben zur Klasse gehen und nach class Parameters suchen, sehen wir, dass diese eigentlich nicht von einem Hash erbt, sie verhält sich nur wie einer. Das ist also eine wirklich nützliche kleine Sache, die mir Colin neulich beigebracht hat: Im Grunde können wir mit with defaults das als Basis-Hash von Werten verwenden. Wenn wir hier den user haben wollen, können wir das tun.3:29 Wir könnten das für Standardwerte bei Radiobuttons oder Checkboxen verwenden, oder was auch immer der Fall sein mag, ein Array. Das ist einfach ein großartiger Weg, das zu tun, falls der Browser tatsächlich nichts übermittelt. Die andere Möglichkeit ist das, was Checkboxen im Browser tun: Wenn Sie ein F.checkbox in Ihrem Post-Formular haben, wenn wir hier einfach form.checkboxhello schreiben, werden Checkboxen nicht an den Browser übermittelt, es sei denn, sie sind tatsächlich markiert. Es gibt also keine Möglichkeit, das in Ihren Formularen abzuwählen. Check underscore box.4:11 Was Sie hier sehen, ist, dass wir dieses hello-Eingabefeld haben, das ein verborgener Wert ist und den Wert auf null setzt. Wenn das also nicht markiert ist, wird dieser verborgene Wert übermittelt, und sie kommen in einer Reihenfolge im Formular an. Wenn das also markiert ist, wird der Wert null gesendet und dann der Wert eins, und die Rails-Parameter können dann herausfinden, dass ja, der letzte Wert der ist, den Sie in Ihrer Rails-App tatsächlich wollen. Wenn wir also unseren Post aktualisieren und uns den Netzwerkrequest ansehen, sehen wir, dass post hello zero übermittelt wurde, aber auch post hello one. Und wenn wir diesen Post bearbeiten, ohne die Box zu markieren, können wir uns dieses Payload ansehen.5:02 Post hello zero war einfach null. Es gab kein one für die markierte Box, weil sie nicht markiert war. Man kann also Eingabefelder in seinem HTML verwenden, um das für Standardwerte funktionieren zu lassen. Aber wenn es Fälle gibt, in denen man möchte, dass der Server sie setzt, zum Beispiel wollen wir sicherstellen, dass der current user hier vom Server gesetzt wird und wir nicht wollen, dass der Nutzer das übermittelt, dann können wir die with-defaults-Methode dafür verwenden, was ich unglaublich nützlich und unglaublich hilfreich fand. Und ich war überrascht, dass ich das noch nicht kannte.5:38 Also dachte ich mir, das wäre der perfekte Screencast, um ihn mit euch zu teilen. Das war es für diese Episode. Ich hoffe, sie hat euch gefallen. Und wir sprechen uns in der nächsten. Peace.

Über dieses Tutorial

Dieses Tutorial fasst einen GoRails-Screencast von Chris Oliver über with_defaults für Action-Controller-Parameter zusammen. Der Screencast ist das Originalwerk. GoRails veröffentlicht ihn sowie den Rest der Serie auf gorails.com.