Ich arbeite an den Übungen für Kapitel 6 von Hartl's Rails 4 Tutorial. In der ersten Übung wird geprüft, ob die E-Mail-Adressen der Benutzer korrekt sind:
require 'spec_helper'
describe User do
.
.
.
describe "email address with mixed case" do
let(:mixed_case_email) { "[email protected]" }
it "should be saved as all lower-case" do
@user.email = mixed_case_email
@user.save
expect(@user.reload.email).to eq mixed_case_email.downcase
end
end
.
.
.
end
Was ich nicht verstehe ist, warum hier die 'reload'-Methode notwendig ist. Wenn @user.email
auf den Inhalt von mixed_case_email
und gespeichert eingestellt ist, sind @user.reload.email
und @user.email
nicht dasselbe? Ich habe die Reload-Methode nur ausprobiert, um es auszuprobieren, und es schien nichts zu ändern.
Was fehlt mir hier?
Ja, in diesem Fall ist @user.reload.email
und @user.email
dasselbe. Es ist jedoch empfehlenswert, @user.reload.email
anstelle von @user.email
zu verwenden, um zu überprüfen, was genau in der Datenbank gespeichert ist. Ich meine, Sie wissen nicht, ob Sie oder jemand in after_save Code hinzufügen, dessen Wert sich ändert. Dann hat dies keine Auswirkungen auf Ihre Tests.
EDIT: Und auch das, was Sie überprüfen, ist das, was in der Datenbank gespeichert ist. @user.reload.email
spiegelt genau das wider, was in der Datenbank gespeichert ist, dann @user.email
.
Es ist wichtig, den Unterschied zwischen In-Memory und Datenbank zu verstehen. Jeder Ruby-Code, den Sie schreiben, befindet sich im Arbeitsspeicher. Bei der Ausführung einer Abfrage wird beispielsweise ein neues Objekt mit den entsprechenden Daten aus der Datenbank erstellt.
# @student is a in-memory object representing the first row in the Students table.
@student = Student.first
Hier ist dein Beispiel mit Kommentaren zur Erklärung
it "should be saved as all lower-case" do
# @user is an in-memory Ruby object. You set it's email to "[email protected]"
@user.email = mixed_case_email
# You persist that objects attributes to the database.
# The database stores the email as downcase probably due to a database constraint or active record callback.
@user.save
# While the database has the downcased email, your in-memory object has not been refreshed with the corresponding values in the database.
# In other words, the in-memory object @user still has the email "[email protected]".
# use reload to refresh @user with the values from the database.
expect(@user.reload.email).to eq mixed_case_email.downcase
end
Eine ausführlichere Erklärung finden Sie hier post .
reload
Lädt die Attribute des Objekts (hier @user) aus der Datenbank neu. Es stellt immer sicher, dass das Objekt die aktuellsten Daten enthält, die aktuell in der Datenbank gespeichert sind.
Damit können wir auch vermeiden
ActiveRecord::StaleObjectError
Dies kommt normalerweise vor, wenn wir versuchen, die alte Version des Objekts zu ändern.
Es sollte dasselbe sein. Der springende Punkt ist, dass die Reload-Methode das Objekt aus der Datenbank neu lädt. Jetzt können Sie überprüfen, ob Ihr neu erstelltes Testobjekt tatsächlich mit den korrekten/erwarteten Attributen gespeichert wird.
Das Beispiel möchte prüfen, ob der before_save
-Rückruf in app/models/user.rb
seine Aufgabe erfüllt. Der before_save
-Rückruf sollte die E-Mail-Adresse jedes Benutzers vor dem Speichern in der Datenbank auf Downcase setzen. In Übung 6 von Kapitel 6 soll daher getestet werden, ob der Wert in der Datenbank, der mit der Methode reload
abgerufen werden kann, effektiv als Downcase gespeichert wird.