As @Mark wrote in the questions, if you don't access the instance variable in a view you can just use a local variable.
I am making web requests from a decoupled frontend, would @current_user always be nil to begin wtih? Can I simply user a regular variable instead?
How do you communicate with your frontend? I assume it does request JSON? Then you need to expose your instance / local variable to your JSON. Something like this:
class UsersController < ApplicationController
def show
render json: { current_user: current_user }
end
private
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&.authenticated?(cookies[:remember_token])
log_in user
@current_user ||= user
end
end
end
end
Also I think in the example from your tutorial, this method is also used to memoize the current user and don't fetch it again / login again. If you split, it might be more clear:
def current_user
@_current_user ||= fetch_current_user
end
def fetch_current_user
if (user_id = session[:user_id])
User.find_by(id: user_id)
elsif (user_id = cookies.signed[:user_id]) # User has closed the browser before and persistent session exists
user = User.find_by(id: user_id)
if user&.authenticated?(cookies[:remember_token])
log_in user
user
end
end
end
Now we store the current user in current_user and don't log it in again or fetch it again from the database (https://en.wikipedia.org/wiki/Memoization). For instance, if you need to do a authentication / authorization check you need to access current_user several times.
class UsersController < ApplicationController
before_action :check_user
def show
render json: { current_user: current_user }
end
private
def check_user
return unless current_user.admin?
render json: {}, status: 404
end
end
Edit
A convention which is often used to indicate that the instance variable is not directly used but only for memoization is to prefix with an underscore.
def current_user
@_current_user ||= fetch_current_user
end
def fetch_current_user; end
The memoization in Ruby is done with ||= which evaluates to @_current_user || @_current_user = fetch_current_user, so @_current_user is only set if @_current_user is logically false. So if a is already set, we don't need to fetch it again and just use the value stored in the instance variable.