-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement the Nfl.schedule class method
- Loading branch information
Showing
4 changed files
with
179 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
module SportsDataApi | ||
module Nfl | ||
|
||
class Exception < ::Exception | ||
end | ||
|
||
class Season | ||
attr_reader :year, :type, :weeks | ||
|
||
def initialize(xml) | ||
@weeks = [] | ||
if xml.is_a? Nokogiri::XML::NodeSet | ||
@year = xml.first["season"].to_i | ||
@type = xml.first["type"].to_sym | ||
@weeks = xml.first.xpath("week").map do |week_xml| | ||
Week.new(week_xml) | ||
end | ||
end | ||
end | ||
end | ||
|
||
class Week | ||
attr_reader :number, :games | ||
|
||
def initialize(xml) | ||
@games = [] | ||
if xml.is_a? Nokogiri::XML::Element | ||
@number = xml["week"].to_i | ||
@games = xml.xpath("game").map do |game_xml| | ||
Game.new(game_xml) | ||
end | ||
end | ||
end | ||
end | ||
|
||
class Game | ||
attr_reader :id, :scheduled, :home, :away, :status | ||
|
||
def initialize(xml) | ||
if xml.is_a? Nokogiri::XML::Element | ||
@id = xml["id"] | ||
@scheduled = Time.parse xml["scheduled"] | ||
@home = xml["home"] | ||
@away = xml["away"] | ||
@status = xml["status"] | ||
end | ||
end | ||
end | ||
|
||
BASE_URL = "http://api.sportsdatallc.org/nfl-%{access_level}%{version}" | ||
SEASONS = [:PRE, :REG, :PST] | ||
|
||
def self.schedule(year, season, version = 1) | ||
base_url = BASE_URL % { access_level: SportsDataApi.access_level, version: version } | ||
season = season.to_s.upcase.to_sym | ||
raise SportsDataApi::Nfl::Exception.new("#{season} is not a valid season") unless season?(season) | ||
url = "#{base_url}/#{year}/#{season}/schedule.xml" | ||
|
||
begin | ||
# Perform the request | ||
response = RestClient.get(url, params: { api_key: SportsDataApi.key }) | ||
|
||
# Load the XML and ignore namespaces in Nokogiri | ||
schedule = Nokogiri::XML(response.to_s) | ||
schedule.remove_namespaces! | ||
|
||
return Season.new(schedule.xpath("/season")) | ||
rescue RestClient::Exception => e | ||
message = if e.response.headers.key? :x_server_error | ||
JSON.parse(error_json, { symbolize_names: true })[:message] | ||
elsif e.response.headers.key? :x_mashery_error_code | ||
e.response.headers[:x_mashery_error_code] | ||
else | ||
"The server did not specify a message" | ||
end | ||
raise SportsDataApi::Exception, message | ||
end | ||
end | ||
|
||
## | ||
# Check if the requested season is a valid | ||
# NFL season type. | ||
# | ||
# The only valid types are: :PRE, :REG, :PST | ||
def self.season?(season) | ||
SEASONS.include?(season) | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,17 @@ | ||
require "sports_data_api/version" | ||
require "nokogiri" | ||
require "rest_client" | ||
|
||
module SportsDataApi | ||
# Your code goes here... | ||
def self.key | ||
"garbage" | ||
end | ||
|
||
def self.access_level | ||
"t" | ||
end | ||
|
||
autoload :Nfl, File.join(File.dirname(__FILE__), 'nfl') | ||
|
||
class Exception < ::Exception; end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
require 'spec_helper' | ||
|
||
describe SportsDataApi::Nfl do | ||
let(:key) { "1234567890abcdef" } | ||
describe ".schedule" do | ||
it "creates a valid Sports Data LLC url" do | ||
SportsDataApi.stub(:key).and_return(key) | ||
RestClient.stub(:get).with("http://api.sportsdatallc.org/nfl-t1/2012/REG/schedule.xml", params: { api_key: key }).and_return(schedule_xml) | ||
subject.schedule(2012, :REG) | ||
end | ||
it "creates a SportsDataApi::Exception when there is no response from the api" do | ||
error = RestClient::ResourceNotFound.new | ||
error.stub_chain(:response, :headers).and_return(Hash.new) | ||
SportsDataApi.stub(:key).and_return(key) | ||
RestClient.stub(:get).and_raise(error) | ||
expect { subject.schedule(2999, :REG) }.to raise_error(SportsDataApi::Exception) | ||
end | ||
|
||
describe "returned data structures" do | ||
before(:each) { RestClient.stub(:get).and_return(schedule_xml) } | ||
let(:season) { SportsDataApi::Nfl.schedule(2012, :REG) } | ||
describe "SportsDataApi::Nfl::Season" do | ||
subject { season } | ||
it { should be_an_instance_of(SportsDataApi::Nfl::Season) } | ||
its(:year) { should eq 2012 } | ||
its(:type) { should eq :REG } | ||
its(:weeks) { should have(17).weeks } | ||
end | ||
describe "SportsDataApi::Nfl::Week" do | ||
subject { season.weeks.first } | ||
it { should be_an_instance_of(SportsDataApi::Nfl::Week) } | ||
its(:number) { should eq 1 } | ||
its(:games) { should have(16).games } | ||
end | ||
describe "SportsDataApi::Nfl::Game" do | ||
subject { season.weeks.first.games.first } | ||
it { should be_an_instance_of(SportsDataApi::Nfl::Game) } | ||
its(:id) { should eq "8c0bce5a-7ca2-41e5-9838-d1b8c356ddc3" } | ||
its(:scheduled) { should eq Time.new(2012, 9, 5, 19, 30, 00, "-05:00") } | ||
its(:home) { should eq "NYG" } | ||
its(:away) { should eq "DAL" } | ||
its(:status) { should eq "closed" } | ||
end | ||
end | ||
end | ||
|
||
describe ".season?" do | ||
context :PRE do | ||
it { subject.season?(:PRE).should be_true } | ||
end | ||
context :REG do | ||
it { subject.season?(:REG).should be_true } | ||
end | ||
context :PST do | ||
it { subject.season?(:PST).should be_true } | ||
end | ||
context :pre do | ||
it { subject.season?(:pre).should be_false } | ||
end | ||
context :reg do | ||
it { subject.season?(:reg).should be_false } | ||
end | ||
context :pst do | ||
it { subject.season?(:pst).should be_false } | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters