Обработка сторонних ответов API 400/500 в моих контроллерах RAILS

Я учусь внедрять сторонние API в мое приложение rails, но с трудом справляюсь с ошибками.

Более конкретно, я пытаюсь реализовать Full Contact API с помощью гема fullcontact-api-ruby. Я разобрался в аутентификации с помощью своего API-ключа и без проблем сделал запрос через консоль, используя методы gem.

Сейчас я пытаюсь использовать методы-обертки API внутри контроллера профилей. Идея состоит в том, чтобы:

  1. Отправьте на контроллер электронное письмо в качестве параметра
  2. Метод Full Contact API 'person()' будет извлекать информацию, связанную с этим письмом.
  3. Будет создан объект профиля, заполняющий его атрибуты с использованием извлеченных данных API.
  4. Если для этого письма нет доступных данных, имеется неверный запрос или ошибка сервера, произойдет ошибка флэш-памяти и произойдет перенаправление.

Я начал писать код вроде:

  # 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'
Другие вопросы по тегам