Как обработать пользователя равным нулю, когда он не обнаружен ActiveRecord :: RecordNotFound - PullRequest
0 голосов
/ 16 октября 2018

Я изучаю только программирование, в частности Ruby on Rails.Проблема, с которой я сталкиваюсь в настоящее время, заключается в том, что я сомневаюсь, как лучше решить мою проблему с чистым кодом, избегая запахов кода или, возможно, чего-то еще.

Итак, у меня есть users_controller, где я проверяю, действителен ли мой jwt: я декодирую его, снимаю user_id и ищу пользователя в БД по ее id.

 def login
    user = decoded_user(permitted_params[:jwt])
    render json: user
  rescue ActiveRecord::RecordNotFound, JWT::DecodeError
    render status: 401, json: { error: 'invalid token' }.to_json
  end

Как видите, в случае, если недопустимый jwt или пользователь не найден, он должен отобразить 401 error, но каким-то образом, когда пользователь nil, rescue ActiveRecord::RecordNotFound не обнаруживает и не отображает200 status когда захочу 401.Когда jwt является действительным или пустым, все работает нормально.

Я думал обернуть его в блок if else в случае nil, хотя мне это не кажется действительно квалифицированным.Не могли бы вы помочь мне провести рефакторинг, пожалуйста?Спасибо!

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Есть два разных способа, как вы можете справиться с этим с минимальными изменениями.

find_by!

Первый - убедиться, что возникает исключение, когда пользователь не найден.Вы использовали find_by, для которого документация гласит:

Если запись не найдена, возвращается nil.

ДляВ Rails много методов поиска, есть варианты с ! в конце.! указывает в контексте Rails, что метод вызовет исключение.Для find_by существует такой же вариант find_by!.Документация для этого метода говорит вам, что он точно такой же, как find_by, за исключением того, что он не вернет nil, но вызовет исключение.

Замените find_by в decode_user с find_by!, и ваш метод должен работать должным образом.

Избегать исключений

Повышение исключений часто рассматривается как антишаблон.Для этого есть много разных причин, но часто используется один аргумент: исключения являются медленными .Если вы посмотрите на код, сгенерированный Rails при использовании скаффолдинга, то увидите, что действия контроллера обычно выглядят так:

def create
  @test = Test.new(test_params)

  if @test.save
    redirect_to @test, notice: 'Test was successfully created.'
  else
    render :new
  end
end

Вы можете использовать тот же шаблон для вашего метода.Сначала расшифруйте пользователя.Затем проверьте, существует ли пользователь, например, с помощью user.present?.Исходя из этого, либо верните успех или неудачу.

Вы увидите этот паттерн в Rails очень часто, и я бы порекомендовал реорганизовать ваш код, чтобы следовать ему и здесь ...

0 голосов
/ 16 октября 2018

Как указывалось в комментариях @ engineermnky , find_by не вызывает исключения .Он просто возвращает ноль , когда нет записи.Вы должны использовать find_by! вместо этого.Ваш код должен выглядеть следующим образом:

def decoded_user(jwt)
  begin 
    User.find_by!(public_id: decode_user_jwt(jwt)) 
  rescue ActiveRecord::RecordNotFound, JWT::DecodeError
  end
end

А метод login можно изменить на

def login
  user = decoded_user(permitted_params[:jwt])
  if user
    render json: user
  else
    render json: {status: 401, error: 'invalid token' }
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...