Ruby on Rails Tutorial - test, reset password

I have problem with understanding one code in Michael Hartl's tutorial. In class PasswordResetsTest, in test "password resets" we took our user from fixtures, we posted to password_resets_path with right mail and we asserted that @user.reset_digest doesn't equal @user.reload.reset_digest. Later, Michael said we need to use assigns method to be able to patch to password_reset_path. He said it's because our user from fixtures doesn't have reset_token, because it is created only in create_reset_digest method. I understand it, but I don't get one thing - why assert_not_equal with pre- and post- reload user's reset_digest passes? I thought it goes like this: reset_digest is nil at first, we post to password_resets_path, which is create action of PasswordResets Controller; in this action we have create_reset_digest method. Reset_digest isn't nil anymore, we reload it and our assert_not_equal passes. But if so, @user from fixtures should also have reset_token now (if its reset_digest was influenced by create action (specifically create_reset_digest method). Can someone please take a look?

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

def create_reset_digest self.reset_token = User.new_token #creating reset_digest end

    def create     @user = User.find_by(email: params[:password_reset][:email].downcase)     if @user     @user.create_reset_digest     [...]     end     end

I am also studying the same tutorial and I may have an explanation if you do not mind the fact that if you are lucky I am as an inexperienced user as you are. Hopefully there will be someone more experienced than us who check my answer in case I wrote bullshit.

You may find a similar context for your question at chapter 8 when a remember_token is created and the book says that “there’s no way for the test to get access to it”. As far as I have understood, the point is in the call of ‘user.remember_token’ or, in your case, ‘user.reset_token’. In the fixtures, user does not have a reset_token: look at the fixtures and you will see, there is not a reset_token attribute. It is true that it takes that attribute dynamically via the create action of the controller, but once you exit from the action, user is back again the user from the fixtures, with no reset_token attribute (that’s why is defined ‘virtual’: once you exit from the create action of the controller it is lost). Using ‘assigns(:user)’ let you have access directly to the user defined in the create action and retrieve the token. Does it make sense?