mmf 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -14
  3. data/TODO.md +2 -0
  4. data/lib/mmf.rb +89 -20
  5. data/lib/mmf/version.rb +1 -1
  6. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 91d04ca8a24c777447c47109eb71c29e6bc316d6
4
- data.tar.gz: e9bdb5bbae64ad863dc676221755fa68ab66272a
3
+ metadata.gz: 577fa4c71578d6efa468ee917c8915f1178e09d3
4
+ data.tar.gz: c841976f767cd266b2da757bad224b6428794891
5
5
  SHA512:
6
- metadata.gz: c3a1c12f413800950bedde603a15d49654befe0c6adb2229f7ecdb57086680dfde514b468b5d4f72ca0281cb9e338505946dd83f83fe6146ac32cf122b8e3527
7
- data.tar.gz: 7599866ce9c031aa2f04609e3a17965c3292d54f5b97548b033a389c8d66298ec10a1ef21b63d380b09ed7c06ab72068d1da62cbb539b3225895dbdf81dac92c
6
+ metadata.gz: cf3a43a2456628d03404d5df9475c1de07e770034415b4ffd6648241cd0fd5737ad90b2b2c262ea43b659ed4e4b41f7860927dac3674d395d67c019cc3d85030
7
+ data.tar.gz: 86a0b1fea879d4961609d50ff4349ef1d827d31a5feac71c20ac4f7add2f273e7dbe1abd29553373cd6a5a666726d81b45d4a2a0f044b32d7e9926e12f50a461
data/README.md CHANGED
@@ -45,22 +45,43 @@ for details on each API call or use the MapMyFitness [I/O docs](https://develope
45
45
  from your browser.
46
46
 
47
47
  ```text
48
- client.me => [get] v7.0/user/self/?params
49
- client.workouts => [get] v7.0/workout/?params
50
- client.add_workout => [post] v7.0/workout/?params
51
- client.deactivate => [post] v7.0/user_deactivation/?params
52
- client.user => [get] v7.0/user/:user_id/?params
53
- client.user_create => [post] v7.0/user/?params
54
- client.user_update => [put] v7.0/user/:user_id/?params
55
- client.user_photo => [get] v7.0/user_profile_photo/:user_id/?params
56
- client.user_stats => [get] v7.0/user_stats/:user_id/?params
57
- client.workout => [get] v7.0/workout/:workout_id/?params
58
- client.achievement => [get] v7.0/acievement/:achievement_id/?params
59
- client.achievements => [get] v7.0/user_acievement/?params
48
+ client.me => [get] v7.0/user/self
49
+ client.deactivate => [post] v7.0/user_deactivation
50
+ client.user => [get] v7.0/user/:user_id
51
+ client.create_user => [post] v7.0/user
52
+ client.update_user => [put] v7.0/user/:user_id
53
+ client.user_photo => [get] v7.0/user_profile_photo/:user_id
54
+ client.user_stats => [get] v7.0/user_stats/:user_id
55
+ client.achievement => [get] v7.0/acievement/:achievement_id
56
+ client.achievements => [get] v7.0/user_acievement
57
+ client.friends => [get] v7.0/user
58
+ client.suggested_friends => [get] v7.0/user
59
+ client.add_friend => [post] v7.0/frendship
60
+ client.remove_friend => [delete] v7.0/friendship/:friendship_id
61
+ client.approve_friend => [put] v7.0/friendship/:friendship_id
62
+ client.friend_requests => [get] v7.0/friendship
63
+ client.activity_types => [get] v7.0/activity_type
64
+ client.activity_type => [get] v7.0/activity_type/:activity_type_id
65
+ client.privacy_options => [get] v7.0/privacy_option
66
+ client.privacy_option => [get] v7.0/privacy_option/:privacy_option_id
67
+ client.add_workout => [post] v7.0/workout
68
+ client.workouts => [get] v7.0/workout
69
+ client.workout => [get] v7.0/workout/:workout_id
70
+ client.course_leaderboard => [get] v7.0/course_leaderboard/:course_id
71
+ client.search_courses => [get] v7.0/course
72
+ client.course => [get] v7.0/course/:course_id
73
+ client.route => [get] v7.0/route/:route_id
74
+ client.routes => [get] v7.0/route
75
+ client.nearby_routes => [get] v7.0/route
76
+ client.add_route => [post] v7.0/route
77
+ client.update_route => [put] v7.0/route/:route_id
78
+ client.remove_route => [delete] v7.0/route/:route_id
79
+ client.bookmarks => [get] v7.0/route_bookmark
80
+ client.add_bookmark => [post] v7.0/route_bookmark/:route_id
81
+ client.remove_bookmark => [delete] v7.0/route_bookmark/:route_bookmark_id
60
82
  ```
61
83
 
62
- All client methods take an optional params hash which is used to build the
63
- RESTful API endpoint URI.
84
+ All client methods take an optional params hash.
64
85
 
65
86
  ## Examples
66
87
 
data/TODO.md ADDED
@@ -0,0 +1,2 @@
1
+ # TODO
2
+ - pagination
data/lib/mmf.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "mmf/version"
2
2
  require 'oauth2'
3
3
  require 'json'
4
+ require 'pp'
4
5
 
5
6
  class Mmf::Client
6
7
  ROOT_URI = "https://oauth2-api.mapmyapi.com/"
@@ -8,27 +9,60 @@ class Mmf::Client
8
9
  VAR = /%\{(.*?)\}/
9
10
  API_MAP = {
10
11
  # user resources
11
- me: { method: :get, endpoint: 'v7.0/user/self' },
12
- workouts: { method: :get, endpoint: 'v7.0/workout' },
13
- add_workout: { method: :post, endpoint: 'v7.0/workout' },
14
- deactivate: { method: :post, endpoint: 'v7.0/user_deactivation', },
12
+ me: { method: :get, endpoint: 'v7.0/user/self' },
13
+ deactivate: { method: :post, endpoint: 'v7.0/user_deactivation', },
14
+ user: { method: :get, endpoint: 'v7.0/user/%{user_id}', defaults: { user_id: :me } },
15
+ create_user: { method: :post, endpoint: 'v7.0/user' },
16
+ update_user: { method: :put, endpoint: 'v7.0/user/%{user_id}', defaults: { user_id: :me } },
17
+ user_photo: { method: :get, endpoint: 'v7.0/user_profile_photo/%{user_id}', defaults: { user_id: :me } },
18
+ user_stats: { method: :get, endpoint: 'v7.0/user_stats/%{user_id}', defaults: { user_id: :me } },
15
19
 
16
- user: { method: :get, endpoint: 'v7.0/user/%{user_id}' },
17
- user_create: { method: :post, endpoint: 'v7.0/user' },
18
- user_update: { method: :put, endpoint: 'v7.0/user/%{user_id}' },
19
- user_photo: { method: :get, endpoint: 'v7.0/user_profile_photo/%{user_id}' },
20
- user_stats: { method: :get, endpoint: 'v7.0/user_stats/%{user_id}' },
20
+ achievement: { method: :get, endpoint: 'v7.0/acievement/%{achievement_id}' },
21
+ achievements: { method: :get, endpoint: 'v7.0/user_acievement', required: [:user], defaults: { user: :me } },
21
22
 
22
- workout: { method: :get, endpoint: 'v7.0/workout/%{workout_id}' },
23
+ # friend resources
24
+ friends: { method: :get, endpoint: 'v7.0/user', required: [:friends_with] },
25
+ suggested_friends: { method: :get, endpoint: 'v7.0/user', required: [:suggested_friends_for, :suggested_friends_source] },
26
+ add_friend: { method: :post, endpoint: 'v7.0/frendship' },
27
+ remove_friend: { method: :delete, endpoint: 'v7.0/friendship/%{friendship_id}' },
28
+ approve_friend: { method: :put, endpoint: 'v7.0/friendship/%{friendship_id}' },
29
+ friend_requests: { method: :get, endpoint: 'v7.0/friendship', required: [:to_user], defaults: { status: 'pending' } },
30
+
31
+ # shared resources
32
+ activity_types: { method: :get, endpoint: 'v7.0/activity_type' },
33
+ activity_type: { method: :get, endpoint: 'v7.0/activity_type/%{activity_type_id}' },
34
+ privacy_options: { method: :get, endpoint: 'v7.0/privacy_option' },
35
+ privacy_option: { method: :get, endpoint: 'v7.0/privacy_option/%{privacy_option_id}' },
36
+
37
+ # workout resources
38
+ add_workout: { method: :post, endpoint: 'v7.0/workout', required: [:activity_type, :name, :start_datetime, :start_locale_timezone] },
39
+ workouts: { method: :get, endpoint: 'v7.0/workout', required: [:user], defaults: { user: :me } },
40
+ workout: { method: :get, endpoint: 'v7.0/workout/%{workout_id}' },
41
+
42
+ # course resources
43
+ search_courses: { method: :get, endpoint: 'v7.0/course' },
44
+ course: { method: :get, endpoint: 'v7.0/course/%{course_id}' },
45
+ # course_leaderboard: { method: :get, endpoint: 'api/0.1/course_leaderboard/%{course_id}', required: [:activity_type_id] },
46
+ # course_history: { method: :get, endpoint: '/api/0.1/course_history/%{course_id}_%{user_id}' },
47
+ # course_map: { method: :get, endpoint: 'api/0.1/course_map/%{course_id}' },
48
+
49
+ # route resources
50
+ route: { method: :get, endpoint: 'v7.0/route/%{route_id}' },
51
+ routes: { method: :get, endpoint: 'v7.0/route', required: [:user], defaults: { user: :me } },
52
+ nearby_routes: { method: :get, endpoint: 'v7.0/route', required: [:close_to_location, :minimum_distance, :maximum_distance] },
53
+ add_route: { method: :post, endpoint: 'v7.0/route' },
54
+ update_route: { method: :put, endpoint: 'v7.0/route/%{route_id}' },
55
+ remove_route: { method: :delete, endpoint: 'v7.0/route/%{route_id}' },
56
+ bookmarks: { method: :get, endpoint: 'v7.0/route_bookmark', required: [:user], defaults: { user: :me } },
57
+ add_bookmark: { method: :post, endpoint: 'v7.0/route_bookmark/%{route_id}' },
58
+ remove_bookmark: { method: :delete, endpoint: 'v7.0/route_bookmark/%{route_bookmark_id}' }
23
59
 
24
- achievement: { method: :get, endpoint: 'v7.0/acievement/%{achievement_id}' },
25
- achievements: { method: :get, endpoint: 'v7.0/user_acievement' }
26
60
  }
27
61
 
28
62
  attr_accessor :client_key, :client_secret, :access_token
29
63
 
30
64
  def initialize
31
- @client_key, @client_secret, @access_token = ""
65
+ @client_key, @client_secret, @access_token = '','',''
32
66
  yield self
33
67
  client = OAuth2::Client.new(client_key, client_secret)
34
68
  @client = OAuth2::AccessToken.new(client, access_token)
@@ -40,35 +74,70 @@ class Mmf::Client
40
74
  end
41
75
  end
42
76
 
77
+ def user_id
78
+ @user_id ||= me['id']
79
+ end
80
+
43
81
  def api
44
82
  API_MAP.any? do |name, details|
45
- vars = details[:endpoint].scan(VAR).flatten
83
+ vars = url_params(details[:endpoint])
46
84
  context = Hash[vars.zip vars.map {|v| ":#{v}"}]
47
85
  endpoint = interpolate(details[:endpoint], context)
48
- puts "client.#{name}".ljust(20) + "=> [#{details[:method]}]".ljust(10) + "#{endpoint}/?params"
86
+ puts "client.#{name}".ljust(30) + "=> [#{details[:method]}]".ljust(12) + endpoint
49
87
  end
50
88
  end
51
89
 
52
90
  private
53
91
 
54
92
  def call(name, params)
55
- method = API_MAP[name][:method]
56
- endpoint = interpolate(API_MAP[name][:endpoint], params)
57
- request(method, endpoint, params)
93
+ method, endpoint = API_MAP[name].values_at(:method, :endpoint)
94
+ required = API_MAP[name].fetch(:required, []) + url_params(endpoint).map(&:to_sym)
95
+ defaults = expand_special(name, API_MAP[name].fetch(:defaults, {}))
96
+ params = defaults.merge(params)
97
+ check_params(name, required, params)
98
+ begin
99
+ request(method, interpolate(endpoint, params), params)
100
+ rescue OAuth2::Error => e
101
+ raise JSON.parse(e.message[1..-1]).pretty_inspect
102
+ end
58
103
  end
59
104
 
60
105
  def request(method, endpoint, params)
61
106
  uri = "#{ROOT_URI}/#{endpoint}"
62
107
  opts = { params: params, headers: {'Api-Key' => client_key} }
63
108
  resp = @client.send(method, uri, opts)
64
- JSON.parse(resp.body)
109
+ find_relevant_data(JSON.parse(resp.body))
110
+ end
111
+
112
+ def find_relevant_data(data)
113
+ case data
114
+ when Hash
115
+ data = data['_embedded'] || data
116
+ data.size == 1 ? data.first[1] : data
117
+ else data
118
+ end
65
119
  end
66
120
 
67
121
  def interpolate(str, context)
68
- vars = str.scan(VAR).flatten
122
+ vars = url_params(str)
69
123
  vars.inject(str) do |str, var|
70
124
  str.gsub("\%{#{var}}", (context[var.to_sym] || context[var.to_s]).to_s)
71
125
  end
72
126
  end
73
127
 
128
+ def expand_special(name, params)
129
+ return params if name == :me
130
+ params.inject({}) {|h, (k,v)| h[k] = (v == :me ? user_id : v); h }
131
+ end
132
+
133
+ def check_params(name, required, actual)
134
+ return if required.all? { |p| actual[p] }
135
+ raise ArgumentError, "Missing one or more required params #{required} for '#{name}' API call. " +
136
+ "Check API docs at https://developer.mapmyapi.com/docs for details."
137
+ end
138
+
139
+ def url_params(url)
140
+ url.scan(VAR).flatten
141
+ end
142
+
74
143
  end
@@ -1,3 +1,3 @@
1
1
  module Mmf
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mmf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Skryl
@@ -64,6 +64,7 @@ files:
64
64
  - LICENSE.txt
65
65
  - README.md
66
66
  - Rakefile
67
+ - TODO.md
67
68
  - lib/mmf.rb
68
69
  - lib/mmf/version.rb
69
70
  - mmf.gemspec
@@ -87,9 +88,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
88
  version: '0'
88
89
  requirements: []
89
90
  rubyforge_project:
90
- rubygems_version: 2.0.3
91
+ rubygems_version: 2.0.6
91
92
  signing_key:
92
93
  specification_version: 4
93
94
  summary: Ruby REST Client for the MapMyFitness API
94
95
  test_files: []
95
- has_rdoc: