1

Ich arbeite durch das Ruby on Rails Tutorial von Michael Hartl und habe ein interessantes Dilemma erzeugt. Ich habe etwas falsch gemacht, also brauche ich deine Hilfe, um das Problem zu finden. Das Problem betrifft die Überprüfung einer Kennworteigenschaft in einem User-Modell. Die erste Validierung dieser Eigenschaft war:Passwort-Validierung schlägt in zwei gegensätzlichen Szenarien fehl

validates :password, presence: true, 
         confirmation: true, 
         length: { minimum: 6 } 

Dieses eine Mindestlänge des Passworts erfordert und ist so konzipiert, um die Situation zu befriedigen, wo ein neuer Benutzer ihre Instanz erstellt.

Ich habe die folgenden Tests erstellt (und ich wünschte, ich hätte Rspec verwendet!), Geführt von dem Buch. Diese Tests prüfen, ob die Validierungen arbeiten:

test "password must not be blank or made up of spaces" do 
    @user.password = @user.password_confirmation = " " 
    assert_not @user.valid? 
end 

test "password must not be empty/nil" do 
    @user.password = @user.password_confirmation = "" 
    assert_not @user.valid? 
end 

Also, wir überprüfen, dass das Passwort-Feld nicht entweder ein Leerzeichen enthalten kann, oder einen Null-Eintrag. Mit den aktuellen Validierungen bestehen diese Tests. Alles ist gut.

Ich habe Fortschritte gemacht, einem Benutzer zu erlauben, sein Profil zu redigieren. Dadurch kann der Benutzer seinen Namen, seine E-Mail-Adresse und sein Passwort/seine Bestätigung ändern, wenn sie dies wünschen. Um einen Benutzer nicht zu ihr Passwort zu erlauben, sich zu ändern, wenn sie nicht wollen, ist eine zusätzliche Überprüfung hinzugefügt, um das Passwort Eigenschaft des Modells, das Hinzufügen allow_blank: true wie:

validates :password, presence: true, 
         confirmation: true, 
         length: { minimum: 6 }, 
         allow_blank: true # added this! 

So kann der Anwender Lassen Sie nun die beiden Passwortfelder leer, wenn sie ihr Profil bearbeiten, wenn sie ihr Profil nicht ändern wollen. Dies erfüllt den Test:

test "successful edit" do 
    log_in_as @user 
    get edit_user_path(@user) 
    assert_template 'users/edit' 
    name = "Foo Bar" 
    email = "[email protected]" 
    patch user_path(@user), params: { user: { name: name, 
              email: email, 
              password: "", 
              password_confirmation: "" } } 
    assert_not flash.empty? 
    assert_redirected_to @user 
    @user.reload 
    assert_equal @user.name, name 
    assert_equal @user.email, email 
end 

Dies ermöglicht es einem Benutzer nur & E-Mail ihren Namen und zu bearbeiten, indem ihre zwei leere Felder Passwort zu verlassen, gibt es keine Notwendigkeit, ihre password zu ändern. Dies wirft einen FAIL auf einem langen Durchlauftest, wie oben beschrieben, wie zum Beispiel:

test "password must not be blank or made up of spaces" do 
    @user.password = @user.password_confirmation = " " 
    assert_not @user.valid? 
end 

Der Test schlägt fehl, da der Benutzer überprüft wird. Der etwas andere Test, der für nil testet, nicht leer, passiert:

test "password must not be empty/nil" do 
    @user.password = @user.password_confirmation = "" 
    assert_not @user.valid? 
end 

So ein Passwort von “” gefangen ist, sondern ein Passwort von “ “ funktioniert gut für einen neuen Benutzer erstellen oder bearbeiten Sie einen vorhandenen Benutzer.

Das Hinzufügen von allow_blank: true zum Benutzermodell Validierung des Passworts scheint dies verursacht zu haben. Also bin ich zwischen zwei fehlgeschlagenen Tests festgefahren. Wenn ich allow_blank: true auslassen, schlägt dieser Test (vollständige Prüfung oben geklebt):

test "successful edit" do 
. 
. 
    patch user_path(@user), params: { user: 
            { name: name, 
             email: email, 
             password: "", 
             password_confirmation: "" } } 
. 
    assert_equal @user.name, name 
    assert_equal @user.email, email 
end 

Senden der leeren password und password_confirmation den Test nicht besteht, da es nicht erlaubt ist, leer zu sein.

Hinzufügen allow_blank: true innerhalb der Validierung besteht diesen Test:

test "password must not be blank or made up of spaces" do 
    @user.password = @user.password_confirmation = " " 
    assert_not @user.valid? 
end 

Diese fehlschlagen ein Benutzer mit einem Passwort erstellt werden können, bestehend aus Räumen. Ein nil Passwort, d. H. Überhaupt keine Zeichen, ist nicht erlaubt. Dieser Test funktioniert.

Das lässt mich in der Position, wo ich entscheiden muss zwischen einem Benutzer ändern/wiederholen ihre zwei Passwort Felder, wenn sie ihr Profil bearbeiten, ODER, ein Szenario, wo ein Benutzer mit einem Passwort bestehend aus einem Leerzeichen registrieren können oder viele Räume, wie dieser Test nicht funktioniert werfen:

test "password must not be blank or made up of spaces" do 
    @user.password = @user.password_confirmation = " " 
    assert_not @user.valid? 
end 

die Zugabe von allow_blank: true umgeht diesen Test oder die Validierung im allgemeinen. Eine password beliebiger Anzahl von Leerzeichen wird akzeptiert, was gegen die Validierung im Modell ist. Wie ist das möglich?

Irgendwelche Gedanken, wie man besser prüft (abgesehen von der Verwendung von Rspec!). Ich verneige mich vor deinem größeren Wissen.

TIA.

[EDIT]

Die vorgeschlagene Änderungen der unter meinem Test-Suite grün Kommentare. Dies war aufgrund der Suite nicht ausreichend. Um die erfolglose Integration zu testen, testeten die vorgeschlagenen Code mehrere Szenarien in einem Rutsch, wie zum Beispiel:

test "unsuccessful edit with multiple errors" do 
    log_in_as @user 
    get edit_user_path(@user) 
    assert_template 'users/edit' 
    patch user_path(@user), params: { user: 
            { name: "", 
             email: "[email protected]", 
             password: "foo", 
             password_confirmation: "bar" } } 
    assert_template 'users/edit' 
    assert_select 'div.alert', "The form contains 3 errors." 
end 

Der wichtigste Teil hier ist immer die Anzahl der zu erwartenden Fehler korrigieren, so dass assert_select das richtige Ergebnis gibt. Ich tat es nicht. Die Fehler sollten leerer Name, ungültiges E-Mail-Format, Passwort zu kurz, pwd & Bestätigung nicht übereinstimmen. Der Fehler für das kurze Passwort wird nicht angezeigt.

Ich entschied mich, zwei weitere Tests durchzuführen, um das Versagen der Validierung von Passwortlänge und Anwesenheit zu demonstrieren. Der Punkt allow_blank ist, dass das Passwort & Bestätigungsfelder nichts in ihnen bei der Bearbeitung des Benutzerprofils haben, so dass es nicht obligatorisch ist, das Passwort jedes Mal einzugeben, wenn das Benutzerprofil bearbeitet wird. Diese Tests sind:

test "unsuccessful edit with short password" do 
    log_in_as @user 
    get edit_user_path(@user) 
    assert_template 'users/edit' 
    patch user_path(@user), params: { user: 
            { name: @user.name, 
             email: "[email protected]", 
             password: "foo", 
             password_confirmation: "foo" } } 
    assert_select 'div.alert', "The form contains 1 error." 
end 

test "unsuccessful edit with blank (spaces) password" do 
    log_in_as @user 
    get edit_user_path(@user) 
    assert_template 'users/edit' 
    patch user_path(@user), params: { user: 
            { name: @user.name, 
             email: "[email protected]", 
             password: " ", 
             password_confirmation: " " } } 
    assert_select 'div.alert', "The form contains 1 error." 
end 

Wenn das Passwort ist geändert, dann sollten die Validierungsregeln anwenden, das heißt das Passwort nicht leer sein sollte und muss eine Mindestlänge aufweisen. Das passiert hier weder im Code, den das Tutorial-Buch vorschlägt, noch im geänderten Code mit on: :create und on: :edit.

+1

https://stackoverflow.com/questions/5123972/ruby-on-rails-password-validation betrachten Sie die Antwort auf diese Frage. – MisterCal

+0

Es gibt einige alternative Implementierungen in dieser Frage, @MisterCal. Neben dem Versuch, eine praktikable Lösung zu finden, stellte OP auch das Problem, dass die bestehende Validierung einer minimalen Länge und Nicht-Blankheit durch den Zusatz von "allow_blank: true" an einem Punkt im Code überschrieben wird, wo "BCrypt" sein sollte Erfassung von Nichtleerheit für neue Benutzer. In der Tat, die "update" Aktion umgeht die Validierung nicht, da ein neuer Benutzer die Validierungsregeln eingehalten hat (sollte!) Und über eine validierte pwd verfügt. Also, wie ermöglicht diese Hinzufügung das Erstellen eines neuen Benutzers im Gegensatz zu den Validierungsregeln? – OnlySteveH

+2

geben Sie nur die Anweisung 'on:: create' an. Und dann erstellen Sie eine weitere Validierung, bei der die Anweisung 'allow_blank' nicht auf:: edit' steht. – MisterCal

Antwort

1

Ich habe das herausgefunden, also posten wir hier, falls andere auf ein ähnliches Problem stoßen.

Ich änderte die Validierungen, um die :update Aktion auf der User, anstatt nur :edit. Dies umfasste die Aktion des Speicherns in der Datenbank und erfasste die kurzen Validierungen für die Kennwortaktualisierung, erlaubte jedoch weiterhin das Erstellen von Kennwörtern für Leerzeichen.

ein wenig von der documentation Überprüfung zeigte mir, dass aus Räumen gemachtnil und Strings mit allow_blank: trueermöglicht. Das Szenario hier möchte ein nil Passwort akzeptabel, aber nicht leer. Die alternative Validierung von allow_nil: true ist hier passender.

Der aktualisierte Code von oben aussieht, in User.rb:

validates :password, presence: true, 
         length: { minimum: 6 }, 
         allow_nil: true, 
         on: [:edit, :update] 

validates :password, presence: true, 
         confirmation: true, 
         length: { minimum: 6 }, 
         on: :create 

Der erweiterte Test-Suite jetzt alle grün.