Luiz E. Luiz E. - 7 months ago 20
Ruby Question

rewrite multiple inline return

I have a method that will return an error or an user, depends on the status of the user, like this

def authenticate
user = User.find_by(email: params[:mail].downcase)
return render json: Errors::EMAIL_NOT_EXISTS, status: 404 if user.nil?
return render json: Errors::WRONG_EMAIL_PASSWORD_COMBINATION, status: 403 unless user.valid_password?(params[:password])
return render json: Errors::EMAIL_NOT_VERIFIED, status: 202 if 'active' != user.activation_state
render json: user, only: %w(access_token first_name last_name), status: 201
end


I'm losing sleep because I think it is too ugly, and should have a better way to handle with multiple return possibilities but I can't see one.

How can I make this better readable without use multiple returns or multiple ifs

Answer

I like the case suggestion above, but there's nothing wrong with using if. However, the if approach would be way clearer if you did not use the single line form of if. In addition, the return keywords would not be necessary, since in Ruby you can assign the result of an if expression to a variable, or simply let it be the return value of the method because it was the last expression evaluated. You could code it like this:

def authenticate

  user = User.find_by(email: params[:mail].downcase)

  stuff = if user.nil?
    { json: Errors::EMAIL_NOT_EXISTS, status: 404 }
  else unless user.valid_password?(params[:password])
    { json: Errors::WRONG_EMAIL_PASSWORD_COMBINATION, status: 403 }
  else if 'active' != user.activation_state
    { json: Errors::EMAIL_NOT_VERIFIED, status: 202 }
  else
    { json: user, only: %w(access_token first_name last_name), status: 201 }
  end

  render stuff
end

An example of using the result of an if expression as the return value of a method is at https://gist.github.com/keithrbennett/6876886030c7d6cf80d1b6fbcfebf7ae.