wake-up-neo.com

Warum die 'reload'-Methode nach dem Speichern des Objekts verwenden? (Hartl Rails Tut 6.30)

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?

28
sixty4bit

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.

32
Hardik

In-Memory vs. Datenbank

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

Dein Beispiel

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 .

20
Derrick Mar
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.

7

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.

4

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.

0
Asarluhi