Обработка сторонних ответов API 400/500 в моих контроллерах RAILS
Я учусь внедрять сторонние API в мое приложение rails, но с трудом справляюсь с ошибками.
Более конкретно, я пытаюсь реализовать Full Contact API с помощью гема fullcontact-api-ruby. Я разобрался в аутентификации с помощью своего API-ключа и без проблем сделал запрос через консоль, используя методы gem.
Сейчас я пытаюсь использовать методы-обертки API внутри контроллера профилей. Идея состоит в том, чтобы:
- Отправьте на контроллер электронное письмо в качестве параметра
- Метод Full Contact API 'person()' будет извлекать информацию, связанную с этим письмом.
- Будет создан объект профиля, заполняющий его атрибуты с использованием извлеченных данных API.
- Если для этого письма нет доступных данных, имеется неверный запрос или ошибка сервера, произойдет ошибка флэш-памяти и произойдет перенаправление.
Я начал писать код вроде:
# controllers/profiles_controller.rb
def create
@intel = FullContact.person(email: params[:email])
if @intel[:status].to_s[0] != "2"
flash[:error] = @intel[:status]
redirect_to profiles_path
else
# Code to create and populate a Profile instance
end
Поскольку в ответах об успехе есть коды состояния в 200-х годах, я предположил, что извлеку код из объекта Json и проверил, начинается ли он с 2, и в этом случае я бы приступил к созданию экземпляра. Это работает, если с ответом все в порядке, так как я могу работать с объектом Json, хранящимся в @intel. Однако, когда ответ находится в 400-ых, Rails 500-ых вызывает исключение, которое завершает работу Rails, не позволяя мне работать с любым объектом JSON:
FullContact::NotFound in ProfilesController#create
GET https://api.fullcontact.com/v2/person.json?apiKey=MY_API_KEY&email=THE_EMAIL_IM_USING_AS_PARAMETER: 404
Я явно делаю что-то не так. Я пытался избежать повышенного исключения с rescue StandardError => e
который работает, но мне интересно, как правильно обрабатывать эти ошибки в моем контроллере. Любая помощь?
--- ОБНОВЛЕНИЕ РЕШЕНИЯ 1
Если я спасу исключение сразу после запроса, как это:
def create
@intel = FullContact.person(email: params[:email])
rescue FullContact::NotFound
if @intel.nil?
flash[:error] = "Can't process request try again later"
redirect_to profiles_path
else
# Code to create and populate a Profile instance
end
Для @intel задано значение nil (т. е. не для объекта ответа JSON). Я подумал, что просто изменил условное выражение, чтобы проверить, является ли @intel нулевым, но по какой-то странной причине, когда ответ успешен, а @intel установлен на объект JSON, первое условное условие не приводит к методу создания объекта. Не уверен, как установить @intel для ответа JSON, даже если ответ не удался.
2 ответа
Идея rescue
Блок должен определить действия, которые происходят при спасении от ошибки.
Правильный способ структурировать ваш метод будет...
def create
@intel = FullContact.person(email: params[:email])
# Code to create and populate a Profile instance
rescue FullContact::NotFound
flash[:error] = "Can't process request try again later"
redirect_to profiles_path
end
Код, который появляется после rescue
выполняется при спасении, в противном случае игнорируется.
формат
begin
# normal code which may or may not encounter a raised error, if no
# raised error, it continues to normal completion
rescue
# code that is only executed if there was a rescued error
ensure
# code that always happens, regardless of rescue or not, could be
# used to ensure necessary cleanup happens even if an exception raised
end
Метод сам по себе является полным begin
блок, так что не нужно begin
а также end
в приведенном выше формате наброски.
Вам не нужно ensure
блок, только что добавил, чтобы показать, что возможность существует. Также есть возможность использовать else
с rescue
но это на другой день:)
Ты можешь сделать
rescue FullContact::NotFound
чтобы спасти только эту ошибку.
Это не похоже на ошибку, позволяющую провести сравнение. Тем не менее, ваше сравнение ошибочно. Поскольку вы конвертируете его в строку, вам нужно сравнить его со строкой
+ Изменить
if @intel[:status].to_s[0] != 2
В
if @intel[:status].to_s[0] != '2'