Actively enumerate what possible return values functions should have and consider possible exceptions

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the functions category.

Last Updated: 2024-12-03

I was getting 404s in the JavaScript production code of Semicolon&Sons when my browser JS fetched the api/user_information endpoint.

This was confusing, since curling THE SAME ENDPIONT worked fine!

Here's the code:

def current_user
  user_id = cookies.signed[:user_id]

  if user_id
    @current_user ||= User.find(user_id)
  else
    @current_user = nil
  end
end

What happened? In short, curl has no cookie state, whereas my browser does. That made curl an incomplete test.

In the browser, the user_id present within the cookies my browser had since been deleted on my development server. But, having not cleared my cookies, my browser still sent that user_id causing my backend code to call find for an id that no longer existed.

The fix: Within this current_user method, the only possible return values I really wanted were user or nil. By using User.find, which throws an exception when a user with that id was not found, current_user would also throw exceptions as a third possible return value, which is not something I ever wanted from it.

I rewrote such that it never throws exceptions. I should have considered this aspect originally instead of blindly reaching for ActiveRecord.find

@current_user ||= User.find_by(id: user_id)

Lesson

Actively ask yourself what set of return values you want a function to have, then analyze the code and ensure that it doesn't possibly return more possible values than that. Be especially on the lookout for sub-functions that can raise exceptions that bubble up.