Wie kann ich in Rails herausfinden, warum ein .save () fehlgeschlagen ist, abgesehen von Validierungsfehlern?

89

Ich habe ein Active Modell , das zurückkehrt truevon valid?(und .errors leer ist ), wird aber zurückkehrt falseaus save(). Wie kann ich herausfinden, warum das Speichern fehlschlägt, wenn die Modellinstanz gültig ist?

kdt
quelle
7
Ich hatte dieses Problem vor ein paar Wochen. Bei einigen Refactoring-Vorgängen wurde eine before_save-Funktion zurückgelassen, die ständig false zurückgibt, was dazu führt, dass das Speichern fehlschlägt.
Jeff Paquette
1
@ Jeff - danke, es stellt sich heraus, dass es eine: before_save-Methode gab, die false zurückgibt. Wie hast du das herausgefunden? War es nur Code-Inspektion?
kdt
Es war eine Codeüberprüfung und ein Unterschied zur Versionskontrolle.
Jeff Paquette

Antworten:

48

Überprüfen Sie alle Ihre Rückrufe.

Ich hatte ein Problem wie dieses, bei dem ich eine "after_validate" -Methode hatte, die fehlschlug, nachdem ich einige Änderungen am Modell vorgenommen hatte. Das Modell war gültig, aber das "after_validate" gab false zurück. Wenn ich es also verwendete model.valid, sagte es true, aber wenn ich es speicherte, gab es mir Validierungsfehler (die vom after_validate-Rückruf durchlaufen wurden). Es war seltsam.

Schauen Sie sich den Anwendungs-Trace an und Sie sollten sehen können, welche Codezeile die Ausnahme auslöst.

Andrew
quelle
2
Laut Jeffs Kommentar stellte sich heraus, dass das Problem ein before_save-Rückruf war, der false zurückgab.
kdt
3
@kdt - genau das war mein Problem. Ich hatte nicht darüber nachgedacht, weil before_save nur dazu gedacht war, eine Eigenschaft festzulegen, sondern weil sie auf einen falschen Wert gesetzt wurde, der implizit zurückgegeben wurde und das Speichern stillschweigend fehlschlug. Auf der positiven Seite habe ich jetzt die Möglichkeit, diesen Code durch Hinzufügen der Zeile zu korrigieren "Hey! That's MY fake leg!" # Believe it or not, this is important. Nicht dass ich das tun würde. ;)
Nathan Long
2
Ein guter Weg, um einen echten Rückgabewert sicherzustellen, isttrue.tap { do_something }
Nathan Long
Wow, was für ein obskures Problem. Ich hätte nie gedacht, dass ein Rückruf, der false zurückgibt, nicht mehr gespeichert wird. Könnte mich jemand auf die Dokumente dazu verweisen? Vielen Dank für den Hinweis!
Andy
112

Versuchen Sie es mit der Bang-Version save!(mit einem Ausrufezeichen am Ende) und überprüfen Sie den resultierenden Fehler.

Andy Lindeman
quelle
4
sparen! löst nur einen RecordNotSaved aus (wenn ich die .message der Ausnahme drucke, erhalte ich nur den Namen der Ausnahmeklasse). Gibt es irgendwo, wo ich nach mehr Details suchen sollte?
kdt
1
Wenn Sie sich im Rails-Entwicklungsmodus befinden, sollte eine vollständige Beschreibung des Fehlers mit Stack-Trace gedruckt werden. Suchen Sie dort nach Hinweisen und / oder posten Sie sie hier.
Andy Lindeman
1
Ich benutze die Konsole, lade das Objekt (zB o = Object.find #id) und mache dann o.save! wie die Antwort sagt. Es wird ausgedruckt, warum nicht gespeichert wird.
pduey
1
Zu Ihrer Information, Anrufe save!können ausgelöst werden ActiveRecord::RecordInvalid(da sie Validierungen ausführen) oder ActiveRecord::RecordNotSavedso möchten Sie sie retten.
Dennis
2
+1, da dies die am wenigsten unbefriedigende Antwort auf die grundlegende Frage ist, wie .saveFehler diagnostiziert werden können , die nicht auf eine Validierung zurückzuführen sind. Die "am wenigsten unbefriedigende" Qualifikation bezieht sich auf Rails, nicht auf diese Antwort.
Chuck Batson
107

Wenn @user.save(zum Beispiel) zurückgegeben wird false, führen Sie dies einfach aus, um alle Fehler zu erhalten:

@user.errors.full_messages
Sam Alex
quelle
12
Wie ich in der Frage erwähnt habe, .valid? ist wahr - dh es gibt keine Validierungsfehler. Ich habe überprüft, dass .errors auch eine leere Liste zurückgibt (ich habe die Frage aktualisiert, um darauf hinzuweisen)
kdt
3

Ja, ich habe dieses Problem behoben, indem ich sichergestellt habe, dass ich in all meinen before_ * -Rückrufen true zurückgebe, dann funktioniert es :)

Bleistiftcheck
quelle
-1

Das Problem war, dass ich vergessen hatte, die Validierung zum Modell hinzuzufügen.

class ContactGroup < ActiveRecord::Base
  validates_presence_of :name
end
Ian Vaughan
quelle