ruby когда / как использовать спасение / обеспечить? - PullRequest
0 голосов
/ 20 марта 2020

У меня есть класс для вызова географического местоположения API. ниже приведен пример URL с Json ответом примерно так:

{ "location": { "lat": 31.0, "lng": 14.0 }, "accuracy": 112.4 }

Я хочу перехватить любые ошибки, такие как 503, 404 или любые другие ошибки, которые могут быть вызваны ошибкой в ​​объекте запроса. что является правильным путем спасения в ruby. также. если есть какая-либо ошибка, могу ли я вернуть сообщение из блока проверки?

def findlocation
  begin
    location = httparty.get("https://www.googleapis.com/geolocation/v1/geolocate?key=#{API_KEY}")
  rescue 
    # do something after catching error
  ensure
    return { "message" : "unable to find location" }
  end 
end

Ответы [ 2 ]

3 голосов
/ 20 марта 2020

В целом исключения должны использоваться для исключительных событий. Нестандартный поток приложения.

При отлове исключений всегда указывайте c и спасайте только те исключения, с которыми вы знаете, что делать.

begin 
  pats "hello world"
rescue 
  nil
end

В этом примере показан серьезный недостаток кода в вашем вопросе - вы создали черную дыру, которая поглощает ошибку NoMethodError, которая могла бы сказать нам, что в коде есть опечатка. Это делает отладку чрезвычайно сложной. Этот анти-шаблон известен как обработка исключений покемонов (должен поймать их всех).

ensure просто гарантирует, что код будет запущен независимо от того, вызвал ли код исключение или нет. Он используется, например, для гарантии того, что метод закрывает обработчик файла, который он открыл, или откатывает транзакцию. Это действительно большой молот, который следует использовать очень экономно.

HTTParty на самом деле не вызывает исключений, когда код ответа является кодом "ошибки" - потому что это не исключительное событие. Это часть нормального потока приложений при работе с HTTP-запросами. Дерьмо случается. HTTParty вызывает исключения, если вы вообще не можете подключиться к серверу или даже не можете добраться до сети Это исключительные события.

class GeolocationClient
  include HTTParty 
  base_uri "https://www.googleapis.com/geolocation/v1"
  format :json
  attr_accessor :options

  def initialize(api_key:)
    @options = {
      api_key: api_key
    }
  end

  def geolocate
    begin 
      response = self.class.get("/geolocate", options)
      if response.successful?
        response 
      else
        logger.info("Geolocation API call was unsuccessful. Status code: #{response.code}")
        handle_unsuccessful_request
      end
    rescue HTTParty::Error => e 
      logger.warn(e.message)
      handle_unsuccessful_request
    end
  end

  private

  def handle_unsuccessful_request
    { "message" : "unable to find location" }
  end
end

response.successful? проверяет, находится ли ответ в 2xx «счастливом диапазоне». Используйте оператор switch, если вы хотите обрабатывать каждый код или диапазон кодов отдельно.

2 голосов
/ 20 марта 2020

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

Допустим, вы хотите возобновить каждую отдельную ошибку, которую вы можете совершить

response = HTTParty.get("https://www.googleapis.com/geolocation/v1/geolocate?key=#{API_KEY}")

case response.code
  when 503
    # do something, Internal Server error
  when 404
    # do something, Page Not found
  when 500...600
    # do something, unexpected error
end

Однако в приведенных выше случаях предполагается, что вы каким-то образом смогли поговорить с запрошенным URL-адресом. Если в любом случае вам не удалось поговорить с сервером и вы хотите избавиться от общей ошибки HTTParty, вы можете сделать

def findlocation
  begin
    response = HTTParty.get("https://www.googleapis.com/geolocation/v1/geolocate?key=#{API_KEY}")
  rescue HTTParty::Error => e 
    # Something is wrong 
    puts "#{e.message}"
end

ensure, позволяющий запустить фрагмент кода вне зависимости от того, является ли исключение происходит. Поэтому, если вы хотите, чтобы фрагмент кода выполнялся независимо от того, удалось ли вам пообщаться с Google API, поместите его в блок обеспечения

...