Michael Hartl’s Rails Tutorial chapter 9 (section 9.12) tests failed "undefined local variable or method"

289 Views Asked by At

I'm going through Michael Hartl’s Rails Tutorial, but implementing advanced log in I got stuck in test (section 9.12).

I had passed all test so far, but then I get an error on testing login with valid information. It seems somehow something is not well defined or missing. Any help? Thanks

Test output

UserLoginTest

    require 'test_helper'

class UsersLoginTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "login with invalid information" do
    get login_path
    assert_template 'sessions/new'
    post login_path, params: {session: {email:"", password:""}}
    assert_template 'sessions/new'
    assert_not flash.empty?
    get root_path
    assert flash.empty?
  end

  test "login with valid information" do
    get login_path
    post login_path, params: { session: { email: @user.email, password: 'password' } }
    assert_redirected_to @user
    follow_redirect!
    assert_template 'users/show'
    assert_select "a[href=?]", login_path, count: 0
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", user_path(@user)
  end

  test "login with valid information followed by logout" do
    get login_path
    post login_path, params: { session: { email: @user.email, password: 'password' } }
    assert is_logged_in?
    assert_redirected_to @user
    follow_redirect!
    assert_template 'users/show'
    assert_select "a[href=?]", login_path, count: 0
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", user_path(@user)
    delete logout_path
    assert_not is_logged_in?
    assert_redirected_to root_url
    follow_redirect!
    assert_select "a[href=?]", login_path
    assert_select "a[href=?]", logout_path,      count: 0
    assert_select "a[href=?]", user_path(@user), count: 0
  end

end

SessionsHelper

module SessionsHelper
def log_in(user)
  session[:user_id] = user.id
end
def current_user
  if (user_id = session[:user_id])
    @current_user ||= User.find_by(id: user_id)
  elsif (user_id = cookies.signed[:user_id])
  user = User.find_by(id: user_id)
  if user && user.authenticated?(cookies[:remember_token])
    log_in user
    @current_user = user
  end
  end   
end
def remember(user)
  user.remember
  cookies.permanent.signed[user_id] = user.id
  cookies.permanent[:remember_token] = user.remember_token
end
def logged_in?
  !current_user.nil?
end
def forget
  user.forget
  cookies.delete(:user_id)
  cookies.delete(:remember_token)   
end
def log_out
  forget(current_user)
  session.delete(:user_id)
  @current_user = nil
end

end SessionsController

    class SessionsController < ApplicationController
  def new
  end

  def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      log_in user
      remember user
      redirect_to user
    else
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end

  def destroy
    log_out
    redirect_to root_url
  end

end
1

There are 1 best solutions below

1
On BEST ANSWER

Your test output says there is an undefined local variable user_id at line 18 of sessions_helper.rb. If we take a look around that line in the code, we see this method:

def remember(user)
  user.remember
  cookies.permanent.signed[user_id] = user.id
  cookies.permanent[:remember_token] = user.remember_token
end

The error occurs where you try to do cookies.permanent.signed[user_id]. You probably forgot a colon and meant to say cookies.permanent.signed[:user_id]. Without the colon, ruby thinks user_id is a local variable instead of a symbol and the error you're seeing is thrown.