Prevent AuthLogic from automatically logging in after creating new user

Last week, I was helping my friend solve an annoying issue in AuthLogic which took me and my colleagues few hours to figure out the solution. And I would like to share it here so that you can avoid this issue in the future and save your day.

We were working on a feature which allows guest user to add items to his shopping cart and signing in later. We had done this kind of feature several times before but mostly with Devise, so we had no much experience working with AuthLogic. But the basic idea is still the same: we create a fake user in database and store that fake user in the session and treat it as current_user. For example, in my application_controller

def current_or_guest_user
  if current_user
    guest_user.destroy
    session[:guest_user_id] = nil
    current_user
  else
    guest_user
  end
end

def guest_user
  User.find_by_id(session[:guest_user_id]) || create_guest_user
end

def create_guest_user
  user = User.create_guest_user
  session[:guest_user_id] = user.id
  user
end

def current_user_session
  return @current_user_session if defined?(@current_user_session)
  @current_user_session = UserSession.find
end

def current_user
  return @current_user if defined?(@current_user)
  @current_user = current_user_session && current_user_session.user
end

From now on, instead of using current_user method like we usually do, we will use current_or_guest_user for reference.

This method would work very fine in Devise but for some reasons, it did not work with AuthLogic. We realized that the guest user was automatically logged in by AuthLogic. And that was the reason why it did not return correct guest user from the database and tried recreating new guest user on every 2 requests. Why every two requests? Here are the requests:

  1. First request: guest user is created, and it become the current_user because of strange behavior of AuthLogic

  2. Second request: we detect and it seems like you are logged in, so we will try destroying the guest_user which is exactly the current user. And you will be logged out from the system because user object has just been destroyed.

  3. Third request: You have already logged out, the same thing happen like the first request.

Solution

How would we solve this? After hours of searching and asking the community, here we come the solution. As far as we understand, AuthLogic would automatically log in the user who has just been created. It means that when you do this:

user = User.new
#set attributes here
#user.abc = '123'
user.save #it become wrong here

This new user will be signed in as default.

If you don't want this to happen, you need to use different method which is the key of this post

user.save_without_session_maintenance

And tada, your application now works as you expected, your guest user will not be auto-logged in and destroyed.

Hopefully this post is helpful to you and please share it with your friend so that they can avoid similar issue we had before.