mmf 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: