Witam, właśnie przerabiam serię screencastów Hartla. Mam problem ze zrozumieniem jednego fragmentu kodu - chodzi o reset hasła, w sytuacji, gdy go nie pamiętamy i chcemy zmienić na nowe. Najpierw udostępniam kod, niżej opiszę mój problem:
require 'test_helper'
class PasswordResetsTest < ActionDispatch::IntegrationTest
def setup
ActionMailer::Base.deliveries.clear
@user = users(:michael)
end
test "password resets" do
get new_password_reset_path
assert_template 'password_resets/new'
# Invalid email
post password_resets_path, password_reset: { email: "" }
assert_not flash.empty?
assert_template 'password_resets/new'
# Valid email
post password_resets_path, password_reset: { email: @user.email }
assert_not_equal @user.reset_digest, @user.reload.reset_digest
assert_equal 1, ActionMailer::Base.deliveries.size
assert_not flash.empty?
assert_redirected_to root_url
# Password reset form
user = assigns(:user)
# Valid password & confirmation
patch password_reset_path(user.reset_token),
email: user.email,
user: { password: "foobaz",
password_confirmation: "foobaz" }
end
end
Akcja create z PasswordResets Controller:
def create
@user = User.find_by(email: params[:password_reset][:email].downcase)
if @user
@user.create_reset_digest
[...]
end
end
Metoda create_reset_digest:
def create_reset_digest
self.reset_token = User.new_token
[...]
end
No i w końcu mój problem. Hartl mówi, że musimy użyć metody assigns, i wyciągnąć usera z controllera, bo tylko ten właśnie @user - z metody create - będzie mieć reset_token, ponieważ ta zmienna jest tworzona w metodzie create_reset_digest - to atrybut wirtualny, nie istnieje w bazie (jest w niej tylko reset_digest). Nie rozumiem w takim razie, czemu nasz użytkownik pobrany z fixtury do testów, wykorzystywany w teście zanim użyliśmy assign - działa? Czemu linijka assert_not_equal @user.reset_digest, @user.reload.reset_digest działa? Jestem osobą początkującą i rozumiem to tak, że wzięliśmy naszego użytkownika - michaela z fixtury i zrobiliśmy post do password_resets_path z prawidłowym mailem, co wywołało akcję create, w której jest właśnie metoda create_reset_digest, dzięki temu nasz michael dostał zarówno token, jak i digest. Użyliśmy więc assert_equal_not, żeby sprawdzić, czy reset_digest, który był do tej pory nilem, dostał jakąś wartość. W takim razie, nasz michael miałby też token. I gdy już wydawało mi się, żę wszystko rozumiem - Hartl mówi, że musimy użyć assigns, bo nasz użytkownik nie ma reset_token. Gdzie popełniam błąd w rozumowaniu?