MaximeD/gem_updater

View on GitHub
lib/gem_updater/ruby_gems_fetcher.rb

Summary

Maintainability
A
45 mins
Test Coverage
# frozen_string_literal: true

require 'json'
require 'nokogiri'
require 'open-uri'

module GemUpdater
  # RubyGemsFetcher is a wrapper around rubygems API.
  class RubyGemsFetcher
    HTTP_TOO_MANY_REQUESTS = '429'

    attr_reader :gem_name

    # @param gem_name [String] name of the gem
    def initialize(gem_name)
      @gem_name = gem_name
    end

    # Finds the changelog uri.
    # It asks rubygems.org for changelog_uri of gem.
    # See API: http://guides.rubygems.org/rubygems-org-api/#gem-methods
    #
    # @return [String|nil] uri of changelog
    def changelog_uri
      response = query_rubygems
      response.to_h['changelog_uri']
    end

    private

    # Parse JSON from a remote url.
    #
    # @param url [String] remote url
    # @return [Hash] parsed JSON
    def parse_remote_json(url)
      JSON.parse(URI.parse(url).open.read)
    end

    # Make the real query to rubygems
    # It may fail in case we trigger too many requests
    #
    # @param tries [Integer|nil] (optional) how many times we tried
    def query_rubygems(tries = 0)
      parse_remote_json("https://rubygems.org/api/v1/gems/#{gem_name}.json")
    rescue OpenURI::HTTPError => e
      # We may trigger too many requests, in which case give rubygems a break
      if e.io.status.include?(HTTP_TOO_MANY_REQUESTS)
        tries += 1
        sleep 1 && retry if tries < 2
      end
    end
  end
end