I've defined a Client class to connect to an external API. The Client class will return XML responses for various resources. Here's what it looks like now:
require 'nokogiri'
class Client
include Exceptions
CONFIG = YAML.load_file(File.join(Rails.root, 'config', 'mark.yml'))
def self.get_leagues_xml(league, start_date, end_date)
raise ArgumentError, "No args can be nil." if league.nil? || start_date.nil? || end_date.nil?
start_date = format_date(start_date)
end_date = format_date(end_date)
@url = build_url_for(:leagues)
@url_params = {'League' => league, 'StartDate' => start_date, 'EndDate' => end_date}
call_http_service
end
def self.get_seasons_xml(season)
raise ArgumentError, "No args can be nil." if season.nil?
@url = build_url_for(:seasons)
@url_params = {'Season' => season}
call_http_service
end
protected
def self.call_http_service
begin
conn = create_connection
resp = get_response(conn)
resp_xml = Nokogiri::XML(resp.body)
rescue Faraday::Error::ClientError => ce
raise MarkClientError.new("Client error occurred trying to access Mark feed at #{@url}: #{ce.message}.")
rescue => e
raise e
end
end
def self.get_response(connection)
connection.get do |req|
req.params['Username'] = CONFIG['api']['username']
req.params['Password'] = CONFIG['api']['password']
@url_params.each_pair { |key, val| req.params[key] = val}
req.options = {:timeout => 30} # open/read timeout in secs
end
end
def self.create_connection
Faraday.new(:url => @url) do |builder|
builder.request :url_encoded
builder.response :logger
builder.adapter :net_http
end
end
def self.build_url_for(resource)
CONFIG['api']['url'] + CONFIG['resource']["#{resource.to_s}"]['url']
end
def self.format_date(date)
date = Chronic.parse(date) if date.is_a?(String)
date.strftime('%m/%d/%Y')
end
end
My primary question is whether or not my use of the class instance variables (@url and @url_params) is an anti-Rubyism and will get me into trouble when multiple concurrent class method calls are being made? I've considered making Client a module or a superclass and then having separate classes for each type of API call that needs to made, for ex, LeaguesClient and SeasonsClient. That way I could make those instantiated classes and initialize with url and url_params. I'm starting to experiment with the distinct nuances of Ruby but want to check with you guys as to how you would approach. Any thoughts you have would be welcome. Thanks!