Search code examples
ruby-on-railsdeviserolify

I'm switching to Devise and I'm unable to view my users index page or individual users


I'm switching my UAM to Devise and Rolify and I'm running into a snag viewing my user index and user show pages.

In the rails console, I'm able to view the user's email via User.first.email so I'm not sure why I'm getting this error about the Nil class.

I'm able to log in and log out with no issues.

In a few of the SOF posts, I saw that the nil class is pointing to the current user being nil but there is some logic built into the navigation menu around current_user so I know that's working as well.

In the screenshot of the Rails error message, it is indicating a params of 1 which should correspond to the user I'm currently logged in with.

Any thoughts? What could I be overlooking?

Here's the full trace:

14:55:04 web.1  | Completed 500 Internal Server Error in 38ms (ActiveRecord: 12.7ms | Allocations: 13119)
14:55:04 web.1  |
14:55:04 web.1  |
14:55:04 web.1  |
14:55:04 web.1  | ActionView::Template::Error (undefined method `email' for nil:NilClass):
14:55:04 web.1  |     1: <div class="container">
14:55:04 web.1  |     2:   <h2>Showing User Details</h1>
14:55:04 web.1  |     3:
14:55:04 web.1  |     4:    <%= image_tag avatar_url(@user), class: "img-circle avatar_large" %>
14:55:04 web.1  |     5:
14:55:04 web.1  |     6:   <div>
14:55:04 web.1  |     7:     <%= link_to "Edit your profile", edit_user_path(@user) %>
14:55:04 web.1  |
14:55:04 web.1  | app/helpers/application_helper.rb:3:in `avatar_url'
14:55:04 web.1  | app/views/users/show.html.erb:4

Screenshot of Rails Error Mesage

Screenshot of User Database in PG

Here's my user controller:

# frozen_string_literal: true

class UsersController < ApplicationController
  before_action :authenticate_user!, only: %i[show edit update destroy]
  before_action :require_user, only: %i[edit update]
  before_action :require_same_user, only: %i[edit update destroy]

  def show
    @events = @user.events
    @events = @user.artists
  end

  def new
    @user = User.new
  end

  def index
    @users = User.all
  end

  def create
    @user = User.new(user_params)
    if @user.save
      session[:user_id] = @user.id
      flash[:notice] = "Welcome to the site #{@user.username}, you have successfully signed up"
      redirect_to user_path(@user)
    else
      render "new"
    end
  end

  def destroy
    @user.destroy
    session[:user_id] = nil if @user == current_user
    flash[:notice] = "Account and all associated events successfully deleted"
    redirect_to root_path
  end

  def edit; end

  def update
    if @user.update(user_params)
      flash[:notice] = "Your account information was successfully updated"
      redirect_to @user
    else
      render "edit"
    end
  end

  private
    def user_params
      params.require(:user).permit(:email, :password)
    end

    def set_user
      @user = User.find(params[:id])
    end

    def require_same_user
      if current_user != @user && !current_user.admin?
        flash[:alert] = "You can only edit or delete your own account"
        redirect_to login_path
      end
    end
end

Here's my user model:

class User < ApplicationRecord
  has_many :events, dependent: :destroy
  has_many :artists, dependent: :destroy
  rolify
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end


Solution

  • Your app/views/users/show.html.erb is looking for a @user variable in your users_controller, which you havent defined in the corresponding show method.

    so you either grab the current_user or the id from the params:

    def show
      @user = current_user
      # OR
      @user = User.find(params[:id])
    end
    

    depending on setup and usecase ...

    EDIT: its also worth mentioning that you do have a set_user method which you arent using: before_action :set_user, only: %i[show edit update destroy]