strava-api-v2 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +18 -0
  2. data/.rvmrc +60 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +100 -0
  6. data/Rakefile +9 -0
  7. data/lib/strava/base_connection.rb +29 -0
  8. data/lib/strava/exceptions.rb +7 -0
  9. data/lib/strava/strava_response.rb +5 -0
  10. data/lib/strava/v1/clubs_request.rb +20 -0
  11. data/lib/strava/v1/connection.rb +22 -0
  12. data/lib/strava/v1/models/athlete.rb +15 -0
  13. data/lib/strava/v1/models/club.rb +14 -0
  14. data/lib/strava/v1/models/effort.rb +17 -0
  15. data/lib/strava/v1/models/ride.rb +23 -0
  16. data/lib/strava/v1/models/segment.rb +19 -0
  17. data/lib/strava/v1/models/stream.rb +17 -0
  18. data/lib/strava/v1/rides_request.rb +60 -0
  19. data/lib/strava/v1/segments_request.rb +31 -0
  20. data/lib/strava/v1/streams_request.rb +15 -0
  21. data/lib/strava/v2/auth_request.rb +17 -0
  22. data/lib/strava/v2/connection.rb +27 -0
  23. data/lib/strava/v2/efforts_request.rb +21 -0
  24. data/lib/strava/v2/models/athlete.rb +15 -0
  25. data/lib/strava/v2/models/auth.rb +15 -0
  26. data/lib/strava/v2/models/effort.rb +19 -0
  27. data/lib/strava/v2/models/segment.rb +26 -0
  28. data/lib/strava/v2/segments_request.rb +21 -0
  29. data/lib/strava/version.rb +3 -0
  30. data/strava-api-v2.gemspec +26 -0
  31. data/test/auth_test.rb +32 -0
  32. data/test/clubs_test.rb +31 -0
  33. data/test/efforts_v2_test.rb +34 -0
  34. data/test/rides_v1_test.rb +62 -0
  35. data/test/segments_v1_request_test.rb +39 -0
  36. data/test/segments_v2_request_test.rb +47 -0
  37. data/test/stream_test.rb +30 -0
  38. data/test/test_data.rb +52 -0
  39. data/test/v1_connection_test.rb +37 -0
  40. data/test/v2_connection_test.rb +37 -0
  41. metadata +190 -0
@@ -0,0 +1,31 @@
1
+ require 'strava/v1/models/segment'
2
+
3
+ module Strava
4
+ module V1
5
+ module SegmentRequest
6
+ SEGMENT_PARAMS_MAP = {
7
+ :club_id => :clubId,
8
+ :athlete_id => :athleteId,
9
+ :athlete_name => :athleteName,
10
+ :start_date => :startDate,
11
+ :end_date => :endDate,
12
+ :start_id => :startId,
13
+ :best => :best
14
+ }
15
+
16
+ def efforts_for_segment_path(id)
17
+ "segments/#{id}/efforts"
18
+ end
19
+
20
+ def segment_with_efforts(id, params = {})
21
+ final_params = {}
22
+ params.each_pair do |key, value|
23
+ raise RequestError.new if SEGMENT_PARAMS_MAP[key].nil?
24
+ final_params[SEGMENT_PARAMS_MAP[key]] = value
25
+ end
26
+ all_json = self.fetch(efforts_for_segment_path(id), final_params)
27
+ Segment.new(all_json["segment"], all_json["efforts"])
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ require 'strava/v1/models/stream'
2
+
3
+ module Strava
4
+ module V1
5
+ module StreamRequest
6
+ def streams_path(id)
7
+ "streams/#{id}"
8
+ end
9
+
10
+ def stream(id)
11
+ Stream.new(self.fetch(streams_path(id), nil))
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require 'strava/v2/models/auth'
2
+
3
+ module Strava
4
+ module V2
5
+ module AuthRequest
6
+ def login_path
7
+ 'authentication/login'
8
+ end
9
+
10
+ def login(email, password)
11
+ auth = Auth.new(self.fetch(login_path(), {:email => email, :password => password}))
12
+ self.set_authorized_user(auth.athlete.id, auth.token)
13
+ return auth
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,27 @@
1
+ require 'httparty'
2
+ require 'strava/base_connection'
3
+ require 'strava/exceptions'
4
+ require 'strava/v2/auth_request'
5
+ require 'strava/v2/efforts_request'
6
+ require 'strava/v2/segments_request'
7
+
8
+ module Strava
9
+ module V2
10
+ class Connection
11
+ include HTTParty
12
+ include Strava::BaseConnection
13
+ include Strava::V2::AuthRequest
14
+ include Strava::V2::EffortsRequest
15
+ include Strava::V2::SegmentsRequest
16
+
17
+ attr_reader :user_id, :token
18
+ base_uri 'http://www.strava.com/api/v2'
19
+ format :json
20
+
21
+ def set_authorized_user(user_id, token)
22
+ @user_id = user_id
23
+ @token = token
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ require 'strava/v2/models/effort'
2
+
3
+ module Strava
4
+ module V2
5
+ module EffortsRequest
6
+ def efforts_path(id)
7
+ "rides/#{id}/efforts"
8
+ end
9
+
10
+ def segments_for_ride(ride_id)
11
+ all_json = self.fetch(efforts_path(ride_id), {})
12
+
13
+ all_segments = []
14
+ all_json["efforts"].each { |effort_json|
15
+ all_segments.push(Segment.new(effort_json["segment"], [effort_json["effort"]]))
16
+ }
17
+ all_segments
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ require 'strava/strava_response'
2
+
3
+ module Strava
4
+ module V2
5
+ class Athlete < StravaResponse
6
+ attr_reader :id, :name, :agreed_to_terms
7
+
8
+ def initialize(json_blob)
9
+ @id = json_blob["id"]
10
+ @name = json_blob["name"]
11
+ @agreed_to_terms = json_blob["agreed_to_terms"]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'strava/strava_response'
2
+ require 'strava/v2/models/athlete'
3
+
4
+ module Strava
5
+ module V2
6
+ class Auth < StravaResponse
7
+ attr_reader :token, :athlete
8
+
9
+ def initialize(json_blob)
10
+ @token = json_blob["token"]
11
+ @athlete = Athlete.new(json_blob["athlete"])
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ require 'strava/strava_response'
2
+ require 'strava/v2/models/segment'
3
+
4
+ module Strava
5
+ module V2
6
+ class Effort < StravaResponse
7
+ attr_reader :id, :elapsed_time, :moving_time, :distance
8
+
9
+ # Initialize the Effort
10
+ # ejs - the effort JSON
11
+ def initialize(ejs)
12
+ @id = ejs["id"]
13
+ @elapsed_time = ejs["elapsed_time"]
14
+ @moving_time = ejs["moving_time"]
15
+ @distance = ejs["distance"]
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ require 'strava/strava_response'
2
+ require 'strava/v2/models/effort'
3
+
4
+ module Strava
5
+ module V2
6
+ class Segment < StravaResponse
7
+ attr_reader :id, :efforts, :name, :climb_category, :start_latlng, :end_latlng, :average_grade
8
+
9
+ # include the efforts in the segment, if applicable
10
+ # jb - the json for the segment
11
+ # ejb - the json for the efforts, in a list
12
+ def initialize(jb, ejb)
13
+ @id = jb["id"]
14
+ @name = jb["name"]
15
+ @climb_category = jb["climb_category"]
16
+ @start_latlng = jb["start_latlng"]
17
+ @end_latlng = jb["end_latlng"]
18
+ @average_grade = jb["avg_grade"]
19
+ @efforts = []
20
+ ejb.each { |effort_json|
21
+ @efforts.push(Effort.new(effort_json))
22
+ }
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ require 'strava/v2/models/segment'
2
+
3
+ module Strava
4
+ module V2
5
+ module SegmentsRequest
6
+ def segments_and_efforts_for_ride_path(ride_id)
7
+ "rides/#{ride_id}/efforts"
8
+ end
9
+
10
+ def segments_and_efforts_for_ride(ride_id)
11
+ all_json = self.fetch(segments_and_efforts_for_ride_path(ride_id), {})
12
+ all_segments = []
13
+ all_json["efforts"].each { |effort_json|
14
+ all_segments.push(Segment.new(effort_json["segment"], [effort_json["effort"]]))
15
+ }
16
+ all_segments
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,3 @@
1
+ module Strava
2
+ VERSION = "0.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'strava/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "strava-api-v2"
8
+ spec.version = Strava::VERSION
9
+ spec.authors = ["Luke StClair"]
10
+ spec.email = ["secureboot@gmail.com"]
11
+ spec.description = %q{API to access strava API, v2}
12
+ spec.summary = %q{Provides access to the strava v1 and v2 apis, which are soon to be deprecated}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "test-unit"
24
+ spec.add_development_dependency "httparty"
25
+ spec.add_development_dependency "mocha"
26
+ end
data/test/auth_test.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'test/unit'
2
+ require 'mocha/setup'
3
+ require 'strava/v2/connection'
4
+ require 'strava/exceptions'
5
+ require 'strava/v2/models/athlete'
6
+ require 'json'
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
8
+ require 'test_data'
9
+
10
+ class AuthTest < Test::Unit::TestCase
11
+
12
+ def setup
13
+ @s = Strava::V2::Connection.new
14
+ end
15
+
16
+ def test_successful_auth
17
+ email = 'secureboot@gmail.com'
18
+ password = 'notatallreal'
19
+
20
+ Strava::V2::Connection.stubs(:get)
21
+ .with("/#{@s.login_path}", {:query => {:email => email, :password => password}})
22
+ .returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_login)))
23
+ result = @s.login(email, password)
24
+ assert_equal("thetoken", result.token)
25
+ # make sure the athlete parses out okay.
26
+ assert result.athlete.is_a?(Strava::V2::Athlete)
27
+
28
+ # be sure the auth for the connection gets set
29
+ assert_equal(7976, @s.user_id)
30
+ assert_equal("thetoken", @s.token)
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ require 'test/unit'
2
+ require 'mocha/setup'
3
+ require 'strava/v1/connection'
4
+ require 'strava/exceptions'
5
+ require 'strava/v1/models/club'
6
+ require 'json'
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
8
+ require 'test_data'
9
+
10
+ class ClubsTest < Test::Unit::TestCase
11
+
12
+ def setup
13
+ @s = Strava::V1::Connection.new
14
+ end
15
+
16
+ def test_clubs
17
+ club_name = "mission"
18
+
19
+ Strava::V1::Connection.stubs(:get)
20
+ .with("/clubs", {:query => {:name => club_name}})
21
+ .returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_clubs)))
22
+
23
+ clubs = @s.clubs(club_name)
24
+
25
+ assert clubs[0].is_a?(Strava::V1::Club)
26
+ assert_equal(11, clubs.length)
27
+ first = clubs[0]
28
+ assert_equal("Mission Cycling", first.name)
29
+ assert_equal(15, first.id)
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ require 'test/unit'
2
+ require 'mocha/setup'
3
+ require 'strava/v2/connection'
4
+ require 'strava/exceptions'
5
+ require 'strava/v2/models/athlete'
6
+ require 'json'
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
8
+ require 'test_data'
9
+
10
+ class EffortsV2Test < Test::Unit::TestCase
11
+
12
+ def setup
13
+ @s = Strava::V2::Connection.new
14
+ end
15
+
16
+ def test_get_efforts_for_ride
17
+ ride_id = 448459
18
+ Strava::V2::Connection.stubs(:get)
19
+ .with("/rides/#{ride_id}/efforts", {:query => {}})
20
+ .returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_v2_efforts)))
21
+ segments = @s.segments_for_ride(ride_id)
22
+ effort = segments[0].efforts[0]
23
+ assert effort.is_a?(Strava::V2::Effort)
24
+ assert_equal(45665444, effort.id)
25
+ assert_equal(12, segments.length)
26
+ assert_equal(634, effort.elapsed_time)
27
+ assert_equal(634, effort.moving_time)
28
+ assert_equal(5342.8, effort.distance)
29
+ assert_equal(852034, segments[0].id)
30
+ assert_equal(1, segments[0].climb_category)
31
+ assert_equal([37.771132132038474,-122.45532101020217], segments[0].start_latlng)
32
+ assert_equal(-0.997671, segments[0].average_grade)
33
+ end
34
+ end
@@ -0,0 +1,62 @@
1
+ require 'test/unit'
2
+ require 'mocha/setup'
3
+ require 'strava/v1/connection'
4
+ require 'strava/exceptions'
5
+ require 'strava/v1/models/athlete'
6
+ require 'json'
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
8
+ require 'test_data'
9
+
10
+ class RidesV1Test < Test::Unit::TestCase
11
+
12
+ def setup
13
+ @s = Strava::V1::Connection.new
14
+ end
15
+
16
+ def test_rides_with_no_params
17
+ Strava::V1::Connection.stubs(:get)
18
+ .with("/#{@s.rides_path}", {:query => {}})
19
+ .returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_rides_no_params)))
20
+ result = @s.rides()
21
+ assert_equal(50, result.length)
22
+ end
23
+
24
+ def test_rides_with_invalid_param
25
+ assert_raise Strava::RequestError do
26
+ @s.rides({:made_up => "whatever"})
27
+ end
28
+ end
29
+
30
+ def test_rides_with_two_valid_params
31
+ Strava::V1::Connection.stubs(:get)
32
+ .with("/#{@s.rides_path}", {:query => {:startId => 77563, :offset => 50}})
33
+ .returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_ride_start_id_and_offset)))
34
+ rides = @s.rides({:start_id => 77563, :offset => 50})
35
+
36
+ assert_equal(52127040, rides[0].id)
37
+ end
38
+
39
+ def test_getting_efforts_for_a_ride
40
+ ride_id = 77563
41
+ Strava::V1::Connection.stubs(:get)
42
+ .with("/rides/#{ride_id}/efforts", {:query => {}})
43
+ .returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_efforts)))
44
+ ride = @s.ride_with_efforts(ride_id)
45
+ assert_equal(ride_id, ride.id)
46
+ assert_equal(5819602, ride.segments[0].efforts[0].id)
47
+ assert_equal(640366, ride.segments[0].id)
48
+ end
49
+
50
+ def test_show_ride_details
51
+ ride_id = 77563
52
+ Strava::V1::Connection.stubs(:get)
53
+ .with("/rides/#{ride_id}", {:query => {}})
54
+ .returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_show_ride_deets)))
55
+ ride = @s.ride(ride_id)
56
+ assert_equal(82369.1, ride.distance)
57
+ assert_equal(1441.02, ride.elevation_gain)
58
+ assert_equal("02/28/10 San Francisco, CA", ride.name)
59
+ assert_equal("julianbill", ride.athlete.username)
60
+ assert_equal(1139, ride.athlete.id)
61
+ end
62
+ end
@@ -0,0 +1,39 @@
1
+ require 'test/unit'
2
+ require 'mocha/setup'
3
+ require 'strava/v1/connection'
4
+ require 'strava/v1/segments_request'
5
+ require 'strava/exceptions'
6
+ require 'json'
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
8
+ require 'test_data'
9
+
10
+ class SegmentsV1RequestTest < Test::Unit::TestCase
11
+
12
+ def setup
13
+ @s = Strava::V1::Connection.new
14
+ end
15
+
16
+ def test_get_efforts_for_segment
17
+ segment_id = 229781
18
+
19
+ Strava::V1::Connection.stubs(:get)
20
+ .with("/segments/#{segment_id}/efforts", {:query => {:best => true}})
21
+ .returns(stub(:code => 200, :parsed_response => (JSON.parse TestData.test_v1_segment_efforts)))
22
+ segment = @s.segment_with_efforts(segment_id, {:best => true})
23
+ assert segment.is_a?(Strava::V1::Segment)
24
+ assert segment.efforts[0].is_a?(Strava::V1::Effort)
25
+ assert_equal(segment_id, segment.id)
26
+ assert_equal(50, segment.efforts.length)
27
+ first = segment.efforts[0]
28
+ assert_equal(801006623, first.id)
29
+ assert_equal(123529, first.athlete.id)
30
+ assert_equal("jimwhimpey", first.athlete.username)
31
+ assert_equal("Jim Whimpey", first.athlete.name)
32
+ end
33
+
34
+ def test_segment_with_bad_param
35
+ assert_raise Strava::RequestError do
36
+ @s.segment_with_efforts(12345, {:made_up => "whatever"})
37
+ end
38
+ end
39
+ end