#ruby-on-rails #ruby-on-rails-6 #active-model-serializers
Вопрос:
Рассмотрим следующий код
class AuthenticatedController < ApplicationController
rescue_from InvalidCredentials, with: :unauthenticated
def current_user
raise InvalidCredentials
end
private
def unauthenticated(_error)
render plain: { error: 'text' }.to_json, status: :unauthorized
end
end
class UsersController < AuthenticatedController
def show
render json: current_user
end
end
Когда я запрашиваю пользователей#показать, он отображается {"error":"text"}
просто отлично.
Но если я изменюсь unauthenticated
на
def unauthenticated(_error)
render json: { error: 'text' }, status: :unauthorized
end
И ресурс отвечает {"status":500,"error":"Internal Server Error"}
тем же .
Трассировка стека:
Started GET "/api/v1/user" for ::1 at 2021-08-25 12:24:30 0300
Processing by Api::V1::UsersController#show as JSON
Parameters: {"user"=>{}}
Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms | Allocations: 214)
InvalidCredentials (InvalidCredentials):
app/controllers/users_controller.rb:in `show'
app/controllers/authenticated_controller.rb:in `current_user'
app/controllers/authenticated_controller.rb:in `unauthenticated'
Таким образом, вызов render json: {}
обработчика приводит к повторению той же ошибки. Но в то же время render plain: ''
этого не происходит.
Что происходит, когда я меняю ключ с plain
на json
и как заставить его реагировать :unauthorized
вместо ошибки сервера при использовании JSON?
Комментарии:
1. Что там в stacktrace?
2. @AmitPatel Я добавил трассировку стека.
Ответ №1:
Я использовал библиотеку active_model_serializers для рендеринга JSON. Он использует scope
опцию render
в качестве имени метода для вызова, и это current_user
по умолчанию. Поэтому библиотека current_user
снова вызвала метод, когда я позвонил render json: ...
, что привело к ошибке.
Я изменил unauthenticated
метод на
def unauthenticated(_error)
render json: { error: 'text' }, status: :unauthorized, scope: nil
end
и это начало работать, как и ожидалось.
Ответ №2:
Основываясь на предоставленной вами информации, проблема, скорее всего, заключается в том, как вы используете rescue_from
Запрос, который вызывает ошибку, должен быть запросом JSON, чтобы это сработало. Например, если вы пытаетесь войти в систему из формы, обычно по умолчанию это HTML-запрос. Способ подтвердить это-использовать raise request.inspect
метод контроллера. Если это так, то простого решения не существует, и вам придется исправить запрос самостоятельно или просто поддержать и то, и другое.