lib/gendered/guesser.rb in gendered-0.0.7 vs lib/gendered/guesser.rb in gendered-0.0.8

- old
+ new

@@ -1,51 +1,84 @@ +require "json" + module Gendered class Guesser + ENDPOINT = "https://api.genderize.io".freeze + USAGE_HEADERS = { + "X-Rate-Limit-Limit" => :limit, + "X-Rate-Limit-Remaining" => :remaining, + "X-Rate-Reset" => :reset + }.freeze - attr_accessor :names, :country_id + attr_reader :usage + attr_accessor :names, :options - def initialize(values, country_id = nil) - raise ArgumentError, "cannot be empty" if Array(values).empty? + def initialize(names, options = {}) + @names = Array(names) + raise ArgumentError, "names cannot be empty" if @names.empty? - @names = Array(values) - @country_id = country_id + @options = Gendered.config.merge(options || {}) + @options[:connection] ||= {} + @usage = { :limit => nil, :remaining => nil, :reset => nil } end def guess! - response = HTTP.get(url) + response = request(request_options) + update_usage(response) + body = parse(response.body) case response.code when 200 + create_names(body) + when 429 + raise RateLimitError.new(body["error"], *@usage.values_at(:limit, :remaining, :reset)) + else + raise GenderedError.new(body["error"]) + end + end - guesses = JSON.parse(response.body) + private - names.collect do |name| - name = Name.new(name) if name.is_a?(String) + def update_usage(response) + USAGE_HEADERS.each { |header, key| @usage[key] = response[header].to_i } + end - guess = case - when guesses.is_a?(Array) - guesses.find { |g| g["name"] == name.value } - else - guesses - end + def create_names(guesses) + names.collect do |name| + name = Name.new(name) if name.is_a?(String) + guess = case + when guesses.is_a?(Array) + guesses.find { |g| g["name"] == name.value } + else + guesses + end - if guess["gender"] - name.gender = guess["gender"].to_sym - name.probability = guess["probability"] - name.sample_size = guess["count"] - end - - name + if guess["gender"] + name.gender = guess["gender"].to_sym + name.probability = guess["probability"] + name.sample_size = guess["count"] end + + name end end - def url - url = "https://api.genderize.io/?" - url += "country_id=#{country_id}&" if country_id + def request_options + options = {} + options[:params] = @options.reject { |k, v| k == :connection || v.nil? } + options[:params]["name[]"] = @names + options[:connection] = @options[:connection] unless @options[:connection].empty? + options + end - name_queries = names.collect.with_index do |name, index| - "name[#{index}]=#{CGI.escape(name.to_s)}" - end - url + name_queries.join("&") + def request(options) + HTTP.get(ENDPOINT, options) + rescue => e + raise GenderedError, "request failed: #{e}" + end + + def parse(response) + JSON.parse(response) + rescue JSON::ParserError => e + raise GenderedError, "cannot parse response JSON: #{e}" end end end