Caven Caven - 1 year ago 56
Ruby Question

What's the impact of sequence between cookies and session when implementing "current_user"?

I am learning how to build a simple authentication function with session and cookies.
I have a

User
model, then
sessions_controller
. I also create
remember_token
column for users table to handle the "remember_me" situation.
This is the relevant code:




sessions_controller

def create
user = User.find_by_email(params[:email])

if user && user.authenticate(params[:password])
session[:user_id] = user.id
if params[:remember_me]
user.generate_token(:remember_token)
cookies.permanent[:remember_token] = user.remember_token
end
redirect_to root_url
flash[:notice] = "Logged in."
else
render "new"
flash[:notice] = "Invaid email or password."
end
end


user.rb

has_secure_password

def generate_token(column)
self[column] = SecureRandom.urlsafe_base64
self.save
end


application_controller

helper_method :current_user

def current_user
if session[:user_id]
@current_user ||= User.find(session[:user_id])
elsif cookies[:remember_token]
@current_user ||= User.find(cookies[:remember_token])
end
end





The code above seems to be working. But at first I actually reversed the code's sequence in
:current_user
, like this:

def current_user
if cookies[:remember_token]
@current_user ||= User.find(cookies[:remember_token])
elsif session[:user_id]
@current_user ||= User.find(session[:user_id])
end
end


This will raise an exception: "Couldn't find User with 'id'= some_token_here"

In this case, why I can't use the cookies[:remember_token] to find the user firstly. Does the sequence matter? Or, if I had some misunderstanding about how session and cookies work?

Answer Source

That is because if you use find, it finds a record by its database id.

What you want is to find by the remember_token column, so User.find_by(remember_token: cookies[:remember_token])

def current_user
  if cookies[:remember_token]
    @current_user ||= User.find_by(remember_token: cookies[:remember_token])
  elsif session[:user_id]
    @current_user ||= User.find(session[:user_id])
  end
end
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download