Denken Sie an eine einfache Rails-Gerüstanwendung mit einer "neuen" Aktion, die ein Formular zum Hinzufügen von Datensätzen zu einer Datenbank mit einer Schaltfläche "Speichern" enthält. Nach der Aktion "create" leitet der Controller die Aktion "show" weiter, wo der Benutzer den Link "edit" verwenden kann, um den gerade eingefügten Datensatz zu bearbeiten. So weit, so einfach.
Wenn der Benutzer stattdessen die Schaltfläche "Zurück" des Browsers verwendet, nachdem er einen Datensatz erstellt hat, um zur Aktion "Neu" zurückzukehren, zeigt der Browser das Formular mit den Werten an, die der Benutzer gerade eingegeben hat. Jetzt ändert er einige Werte und drückt erneut "Speichern". Er denkt, dass dies den Rekord verändern würde, aber das schafft natürlich einen neuen Rekord.
Was ist der bevorzugte Weg, um solche doppelten Einträge zu verhindern? Ich suche nach einer allgemeinen Lösung, vielleicht basierend auf Cookies oder JavaScript.
Nach einigen Untersuchungen fand ich eine geeignete Lösung auf Basis von Cookies. Hier ist es:
In der Aktion "new" des Controllers wird ein Zeitstempel mit der aktuellen Uhrzeit generiert und in der Form als verstecktes Feld gerendert. Wenn der Benutzer das Formular abschickt, kehrt dieser Zeitstempel zur "create" Aktion des Controllers zurück. Nach dem Erstellen des Datensatzes wird dieser Zeitstempel im Sitzungscookie gespeichert. Wenn der Benutzer über den Zurück-Button des Browsers zum "neuen" Formular zurückkehrt, erhält er ein veraltetes Formular, was bedeutet, dass sein Zeitstempel älter ist als der im Cookie gespeicherte. Dies wird vor dem Erstellen des Datensatzes überprüft und führt zu einer Fehlermeldung.
Hier ist der Controller-Code:
%Vor%Und hier der Formularcode:
%Vor% Als ich das gleiche Problem hatte, habe ich dieses kleine Juwel geschaffen, das es löst. Wenn der Benutzer zurückschlägt, wird er zum edit_path
des Datensatzes umgeleitet, anstatt zurück zum new_path
.
Sie können etwas tun wie:
%Vor%Ihre Modellvalidierungen stellen sicher, dass Dinge wie E-Mail-Adressen einzigartig sind, aber ich denke, dass es mehr um Usability und Erfahrung als alles andere geht.
Angenommen, Sie sprechen über ein Kontoerstellungsformular. Zuallererst sollte der Formular-Senden-Button etwas wie "Konto erstellen" enthalten, anstatt nur "Absenden". Je nachdem, ob der Vorgang erfolgreich war oder nicht, zeigen Sie eine Nachricht an, wie entweder "Konto erfolgreich erstellt" oder "Beim Erstellen Ihres Kontos sind Fehler aufgetreten". Wenn der Benutzer diese Nachricht sieht, wird er wissen, was passiert ist.
Sicher, Sie können nicht verhindern, dass jemand den Zurück-Knopf drückt und erneut auf Enter klickt, aber Sie sollten für die meisten Anwendungsfälle entwerfen. Wenn sie zurückschlagen, sehen sie die Schaltfläche "Konto erstellen". Sie sollten wahrscheinlich einen anderen Text auf der Seite haben, der besagt "Bitte melden Sie sich für ein neues Konto an, um loszulegen".
Nur meine $ 0,02.
Session oder Cookie können zu Nebeneffekten führen.
Ich stimme völlig zu: Wenn es eine Möglichkeit gibt, mit Ihrem Modell zu validieren, ist dies der sicherste Weg, doppelte Datensätze zu vermeiden.
Du kannst immer noch zwei Sachen machen. Browser-Caching verhindern: Felder werden im Formular leer angezeigt, wenn der Benutzer auf klickt die Zurück-Schaltfläche . Und deaktivieren Sie die Schaltfläche "Erstellen", wenn Sie darauf klicken.
%Vor%Wenn Ihr Benutzer die Zurück-Taste drückt, wird die Schaltfläche deaktiviert.
Sie können mithilfe von Validatoren sicherstellen, dass keine doppelten Werte eingefügt werden. In diesem Fall validates_uniqueness_of :field
Wenn Sie beispielsweise verhindern möchten, dass Benutzer dieselbe E-Mail-Adresse haben, können Sie den folgenden Code in Ihr Benutzermodell einfügen.
%Vor%Dies überprüft die Spalte auf vorherige Einträge, die mit denen identisch sind, die Sie inaktivieren möchten. Viel Glück
basiert auf @Georg Ledermann antwort ich mache diesen kleinen Ausschnitt aus Code zum Umleiten, um den Pfad zu bearbeiten, wenn der Benutzer zurückschlägt und dann auf create klickt.
%Vor% %Vor%Fügen Sie schließlich den @ stale_form_check-Parameter zu Ihrem Formular hinzu
%Vor%Sie können diese Methode immer dort abstrahieren, wo Sie sie brauchen, aber auf diese Weise können Sie viele Wiederholungen in Ihrem Projekt vermeiden, wenn Sie dieses Verhalten in vielen Teilen benötigen.
Ich hoffe, es hilft dem nächsten, ich benutzte redirect_on_back gem, aber es funktionierte diesmal nicht für mich, der _usec-Parameter, den dieses Juwel verwendet, wurde immer zurückgesetzt, so dass es nicht jedes Mal vergleichen kann wenn es nötig war
Hier ist etwas, das für mich funktioniert hat.
Sie müssen 2 Dinge tun: Erstellen Sie eine Methode in Ihrem Controller und fügen Sie eine bedingte Anweisung in demselben Controller unter Ihrer 'create' Methode hinzu.
1) Ihre Methode sollte die Gesamtanzahl des Objekts von diesem Benutzer zurückgeben.
EX:
definierter Benutzer current_user.object.count Ende
2) Fügen Sie in Ihrer 'create' Methode eine bedingte Anweisung hinzu.
BEISPIEL:
def erstellen @object = Object.create (object_params) @ object.save wenn Benutzer == 0 redirect_to x_path Ende
Ich hoffe, das hilft!
Tags und Links ruby-on-rails controller browser crud