naudo-ruby-iactionable 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.gitignore +4 -0
  2. data/CHANGELOG.md +29 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +39 -0
  5. data/README.md +49 -0
  6. data/Rakefile +1 -0
  7. data/lib/iactionable/api.rb +224 -0
  8. data/lib/iactionable/connection.rb +118 -0
  9. data/lib/iactionable/error.rb +17 -0
  10. data/lib/iactionable/objects.rb +27 -0
  11. data/lib/iactionable/objects/achievement.rb +29 -0
  12. data/lib/iactionable/objects/awardable.rb +50 -0
  13. data/lib/iactionable/objects/challenge.rb +27 -0
  14. data/lib/iactionable/objects/goal.rb +30 -0
  15. data/lib/iactionable/objects/i_actionable_object.rb +40 -0
  16. data/lib/iactionable/objects/identifier.rb +17 -0
  17. data/lib/iactionable/objects/leaderboard.rb +15 -0
  18. data/lib/iactionable/objects/leaderboard_report.rb +30 -0
  19. data/lib/iactionable/objects/level.rb +24 -0
  20. data/lib/iactionable/objects/level_type.rb +15 -0
  21. data/lib/iactionable/objects/point_type.rb +15 -0
  22. data/lib/iactionable/objects/profile_achievements.rb +20 -0
  23. data/lib/iactionable/objects/profile_challenges.rb +20 -0
  24. data/lib/iactionable/objects/profile_goals.rb +20 -0
  25. data/lib/iactionable/objects/profile_level.rb +20 -0
  26. data/lib/iactionable/objects/profile_notifications.rb +29 -0
  27. data/lib/iactionable/objects/profile_points.rb +29 -0
  28. data/lib/iactionable/objects/profile_summary.rb +32 -0
  29. data/lib/iactionable/objects/progress.rb +46 -0
  30. data/lib/iactionable/settings.rb +30 -0
  31. data/lib/iactionable/version.rb +3 -0
  32. data/lib/ruby-iactionable.rb +9 -0
  33. data/ruby_iactionable.gemspec +28 -0
  34. data/spec/api/get_achievements_api_response_spec.rb +46 -0
  35. data/spec/api/get_challenges_api_response_spec.rb +42 -0
  36. data/spec/api/get_goals_api_response_spec.rb +46 -0
  37. data/spec/api/get_leaderboard_api_response_spec.rb +76 -0
  38. data/spec/api/get_profile_achievements_api_response_spec.rb +113 -0
  39. data/spec/api/get_profile_api_response_spec.rb +103 -0
  40. data/spec/api/get_profile_challenges_api_response_spec.rb +99 -0
  41. data/spec/api/get_profile_goals_api_response_spec.rb +103 -0
  42. data/spec/api/get_profile_notifications_api_response_spec.rb +75 -0
  43. data/spec/api/get_profile_points_api_response_spec.rb +67 -0
  44. data/spec/api_spec.rb +399 -0
  45. data/spec/connection_spec.rb +111 -0
  46. data/spec/settings_spec.rb +52 -0
  47. data/spec/spec_helper.rb +1 -0
  48. metadata +165 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ .bundle
3
+ .DS_Store
4
+ .rvmrc
data/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ # CHANGELOG #
2
+
3
+ ## 0.1.1 ##
4
+
5
+ * changing use of Date to DateTime;
6
+
7
+ ## 0.1.0 ##
8
+
9
+ * New feature: api instance can be set to not wrap raw response within objects with: `@api.set\_object\_wrapping(false)`
10
+
11
+ ## 0.0.5 ##
12
+
13
+ * Fixed: IActionable::Objects::Awardable#awarded_on was stripping out time information when converting IActionable timestamp to Ruby time object
14
+
15
+ ## 0.0.4 ##
16
+
17
+ * explicitly rescuing from timeout errors.
18
+
19
+ ## 0.0.3 ##
20
+
21
+ * Gem name matches require string.
22
+
23
+ ## 0.0.2 ##
24
+
25
+ * Gem name matches require string.
26
+
27
+ ## 0.0.1 ##
28
+
29
+ * Pulling API wrapper out as separate gem (this).
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ruby_iactionable.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,39 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ruby-iactionable (0.1.1)
5
+ activesupport (>= 3.0.0)
6
+ faraday
7
+ faraday_middleware (~> 0.8.7)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ activesupport (3.2.3)
13
+ i18n (~> 0.6)
14
+ multi_json (~> 1.0)
15
+ diff-lcs (1.1.3)
16
+ faraday (0.8.0)
17
+ multipart-post (~> 1.1)
18
+ faraday_middleware (0.8.7)
19
+ faraday (>= 0.7.4, < 0.9)
20
+ i18n (0.6.0)
21
+ multi_json (1.3.5)
22
+ multipart-post (1.1.5)
23
+ rspec (2.10.0)
24
+ rspec-core (~> 2.10.0)
25
+ rspec-expectations (~> 2.10.0)
26
+ rspec-mocks (~> 2.10.0)
27
+ rspec-core (2.10.0)
28
+ rspec-expectations (2.10.0)
29
+ diff-lcs (~> 1.1.3)
30
+ rspec-mocks (2.10.1)
31
+ yard (0.8.1)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ rspec (>= 2.6)
38
+ ruby-iactionable!
39
+ yard
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # Overview #
2
+
3
+ Ruby IActionable is a straightforward wrapper for IActionable's restful API. The JSON-encoded responses from IActionable are wrapped in objects that provide a few extra functions here and there, but are mostly just a representation of the API response.
4
+
5
+ # How To Use #
6
+
7
+ ## Installation ##
8
+
9
+ gem install ruby-iactionable
10
+
11
+ ## IRB ##
12
+
13
+ require 'ruby-iactionable'
14
+
15
+ ## Bundler ##
16
+
17
+ gem 'ruby-iactionable'
18
+
19
+ ## API Credentials And Initialization ##
20
+
21
+ Before the API wrapper can be instantiated or used it must be pre-initialized with your IActionable credentials and version number (IActionable supports older versions but recommends staying up to date):
22
+
23
+ IActionable::Api.init_settings( :app_key => "12345",
24
+ :api_key => "abcde",
25
+ :version => 3 )
26
+ @api = IActionable::Api.new
27
+
28
+ The responses for each of the endpoints of IActionable's API are described through example by [their documentation](http://www.iactionable.com/api/). Here is an example of the response from a [profile summary](http://iactionable.com/api/) returned as an object by the wrapper.
29
+
30
+ profile_summary = @api.get_profile_summary("user", "username", "zortnac", 10)
31
+ profile_summary.display_name # => "Chris Eberz"
32
+ profile_summary.identifiers.first # => instance of IActionable::Objects::Identifier
33
+ profile_summary.identifiers.first.id_type # => "username"
34
+ profile_summary.identifiers.first.id # => "zortnac"
35
+
36
+ Each object can be dumped back in to its original form of arrays and key/value pairs:
37
+
38
+ profile_summary.to_hash # => { "DisplayName" => "Chris Eberz", "Identifiers" => [ {"ID" => "zortnac", "IDType" => "username", ...} ] ... }
39
+ # (not shown in entirety)
40
+
41
+ ----------------
42
+
43
+ ## IActionable ##
44
+
45
+ [Visit their website!](http://www.iactionable.com)
46
+
47
+ ## Author ##
48
+
49
+ Christopher Eberz; chris@chriseberz.com; @zortnac
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,224 @@
1
+ require 'iactionable/connection.rb'
2
+ require 'iactionable/settings.rb'
3
+ require 'iactionable/objects.rb'
4
+
5
+ module IActionable
6
+
7
+ class Api
8
+ attr :connection
9
+ attr :wrap_in_object
10
+
11
+ @@settings = nil
12
+
13
+ def initialize
14
+ if @@settings
15
+ @connection = IActionable::Connection.new(@@settings)
16
+ else
17
+ raise IActionable::ConfigError.new("IActionable::Api cannot be initialized without credentials being set in IActionable::Api.init_settings()")
18
+ end
19
+ @wrap_in_object = true
20
+ end
21
+
22
+ def self.init_settings(values)
23
+ @@settings = IActionable::Settings.new(values)
24
+ rescue IActionable::ConfigError => e
25
+ raise e
26
+ end
27
+
28
+ def self.settings
29
+ @@settings
30
+ end
31
+
32
+ def set_object_wrapping(bool)
33
+ @wrap_in_object = !!bool
34
+ self
35
+ end
36
+
37
+ # =================
38
+ # = Event Logging =
39
+ # =================
40
+
41
+ def log_event(profile_type, id_type, id, event_key, event_attrs = {})
42
+ response = @connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}/events/#{event_key}").with_params(event_attrs).post
43
+ end
44
+
45
+ # =====================
46
+ # = Profile API calls =
47
+ # =====================
48
+
49
+ def get_profile_summary(profile_type, id_type, id, achievement_count = nil)
50
+ request = @connection.request.with_app_key.to("/#{profile_type}/#{id_type}/#{id}")
51
+ request.with_params(:achievementCount => achievement_count) unless achievement_count.blank?
52
+ if @wrap_in_object
53
+ IActionable::Objects::ProfileSummary.new(request.get)
54
+ else
55
+ request.get
56
+ end
57
+ end
58
+
59
+ def create_profile(profile_type, id_type, id, display_name = nil)
60
+ request = @connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}")
61
+ request.with_params(:displayName => display_name) unless display_name.blank?
62
+ request.post
63
+ end
64
+ alias_method :update_profile, :create_profile
65
+
66
+ def add_profile_identifier(profile_type, id_type, id, alt_id_type, alt_id)
67
+ @connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}/identifiers/#{alt_id_type}/#{alt_id}").post
68
+ end
69
+
70
+ # ====================
71
+ # = Points API calls =
72
+ # ====================
73
+
74
+ def get_profile_points(profile_type, id_type, id, point_type)
75
+ response = @connection.request.with_app_key.to("/#{profile_type}/#{id_type}/#{id}/points/#{point_type}").get
76
+ if @wrap_in_object
77
+ IActionable::Objects::ProfilePoints.new(response)
78
+ else
79
+ response
80
+ end
81
+ end
82
+
83
+ def update_profile_points(profile_type, id_type, id, point_type, amount, reason = nil)
84
+ request = @connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}/points/#{point_type}").with_params(:value => amount)
85
+ request.with_params(:description => reason) unless reason.blank?
86
+ if @wrap_in_object
87
+ IActionable::Objects::ProfilePoints.new(request.post)
88
+ else
89
+ request.post
90
+ end
91
+ end
92
+
93
+ # =========================
94
+ # = Achievement API calls =
95
+ # =========================
96
+
97
+ def get_profile_achievements(profile_type, id_type, id, filter_type = nil)
98
+ request = @connection.request.with_app_key
99
+ case filter_type
100
+ when :completed
101
+ request.to("/#{profile_type}/#{id_type}/#{id}/achievements/Completed")
102
+ when :available
103
+ request.to("/#{profile_type}/#{id_type}/#{id}/achievements/Available")
104
+ else
105
+ request.to("/#{profile_type}/#{id_type}/#{id}/achievements")
106
+ end
107
+
108
+ if @wrap_in_object
109
+ IActionable::Objects::ProfileAchievements.new(request.get)
110
+ else
111
+ request.get
112
+ end
113
+ end
114
+
115
+ def get_achievements()
116
+ response = @connection.request.with_app_key.to("/achievements").get
117
+ if @wrap_in_object
118
+ response.map{|achievement_json| IActionable::Objects::Achievement.new(achievement_json)}
119
+ else
120
+ response
121
+ end
122
+ rescue NoMethodError => e
123
+ []
124
+ end
125
+
126
+ # ========================
127
+ # = Challenges API calls =
128
+ # ========================
129
+
130
+ def get_profile_challenges(profile_type, id_type, id, filter_type = nil)
131
+ request = @connection.request.with_app_key
132
+ case filter_type
133
+ when :completed
134
+ request.to("/#{profile_type}/#{id_type}/#{id}/challenges/Completed")
135
+ when :available
136
+ request.to("/#{profile_type}/#{id_type}/#{id}/challenges/Available")
137
+ else
138
+ request.to("/#{profile_type}/#{id_type}/#{id}/challenges")
139
+ end
140
+
141
+ if @wrap_in_object
142
+ IActionable::Objects::ProfileChallenges.new(request.get)
143
+ else
144
+ request.get
145
+ end
146
+ end
147
+
148
+ def get_challenges()
149
+ response = @connection.request.with_app_key.to("/challenges").get
150
+ if @wrap_in_object
151
+ response.map{|challenge_json| IActionable::Objects::Challenge.new(challenge_json)}
152
+ else
153
+ response
154
+ end
155
+ rescue NoMethodError => e
156
+ []
157
+ end
158
+
159
+ # ===================
160
+ # = Goals API calls =
161
+ # ===================
162
+
163
+ def get_profile_goals(profile_type, id_type, id, filter_type = nil)
164
+ request = @connection.request.with_app_key
165
+ case filter_type
166
+ when :completed
167
+ request.to("/#{profile_type}/#{id_type}/#{id}/goals/Completed")
168
+ when :available
169
+ request.to("/#{profile_type}/#{id_type}/#{id}/goals/Available")
170
+ else
171
+ request.to("/#{profile_type}/#{id_type}/#{id}/goals")
172
+ end
173
+
174
+ if @wrap_in_object
175
+ IActionable::Objects::ProfileGoals.new(request.get)
176
+ else
177
+ request.get
178
+ end
179
+ end
180
+
181
+ def get_goals()
182
+ response = @connection.request.with_app_key.to("/goals").get
183
+ if @wrap_in_object
184
+ response.map{|goal_json| IActionable::Objects::Goal.new(goal_json)}
185
+ else
186
+ response
187
+ end
188
+ rescue NoMethodError => e
189
+ []
190
+ end
191
+
192
+ # =========================
193
+ # = Leaderboard API calls =
194
+ # =========================
195
+
196
+ def get_leaderboard(profile_type, point_type, leaderboard, page_number=nil, page_count=nil, id=nil, id_type=nil)
197
+ request = @connection.request.with_app_key.to("/#{profile_type}/leaderboards/points/#{point_type}/#{leaderboard}")
198
+ request.with_params(:pageNumber => page_number) unless page_number.blank?
199
+ request.with_params(:pageCount => page_count) unless page_count.blank?
200
+ request.with_params(:id => id) unless id.blank? || id_type.blank?
201
+ request.with_params(:idType => id_type) unless id.blank? || id_type.blank?
202
+
203
+ if @wrap_in_object
204
+ IActionable::Objects::LeaderboardReport.new(request.get)
205
+ else
206
+ request.get
207
+ end
208
+ end
209
+
210
+ # ===================================
211
+ # = Profile Notifications API calls =
212
+ # ===================================
213
+
214
+ def get_profile_notifications(profile_type, id_type, id)
215
+ response = @connection.request.with_app_key.to("/#{profile_type}/#{id_type}/#{id}/notifications").get
216
+
217
+ if @wrap_in_object
218
+ IActionable::Objects::ProfileNotifications.new(response)
219
+ else
220
+ response
221
+ end
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,118 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+ require 'iactionable/error'
4
+
5
+ module IActionable
6
+ class Request < Struct.new(:path, :params, :headers, :body)
7
+ attr :settings
8
+
9
+ def initialize(settings)
10
+ @settings = settings
11
+ self.path = nil
12
+ self.params = {}
13
+ self.headers = {}
14
+ self.body = {}
15
+ end
16
+
17
+ def to(path)
18
+ self.path = path unless path.nil? || path.empty?
19
+ self
20
+ end
21
+
22
+ def with_api_key
23
+ (self.headers[:Authorization] = @settings.api_key) and self
24
+ end
25
+
26
+ def with_app_key
27
+ (self.params[:appKey] = @settings.app_key) and self
28
+ end
29
+
30
+ def with_params(params={})
31
+ self.params.merge!(params) and self
32
+ end
33
+
34
+ def with_body(body={})
35
+ self.body.merge!(body) and self
36
+ end
37
+ end
38
+
39
+ class Connection
40
+ attr :connection
41
+ attr :settings
42
+ attr :request
43
+ attr_accessor :response
44
+
45
+ def initialize(settings)
46
+ @settings = settings
47
+
48
+ @connection = Faraday.new api_url(@settings.version) do |builder|
49
+ builder.use FaradayMiddleware::ParseJson, content_type: 'application/json'
50
+ builder.use Faraday::Response::RaiseError
51
+ builder.use Faraday::Adapter::NetHttp
52
+ end
53
+
54
+ @request = nil
55
+ end
56
+
57
+ def request
58
+ (@request = Request.new(@settings)) and self
59
+ end
60
+
61
+ def get(path=nil, query_params={})
62
+ @request ||= Request.new(@settings)
63
+ @request.to(path).with_params(query_params)
64
+ @response = @connection.get do |req|
65
+ req.headers.merge! @request.headers
66
+ req.url @request.path, @request.params
67
+ end
68
+ @response.body
69
+ rescue Faraday::Error::ClientError => e
70
+ handle_client_error e
71
+ rescue Faraday::Error::TimeoutError, Timeout::Error => e
72
+ raise e
73
+ ensure
74
+ @request = nil
75
+ end
76
+
77
+ def post(path=nil, query_params={}, body_params={})
78
+ @request ||= Request.new(@settings)
79
+ @request.to(path).with_params(query_params)
80
+ @response = @connection.post do |req|
81
+ req.headers.merge! @request.headers
82
+ req.url @request.path, @request.params
83
+ req.body = @request.body unless @request.body.empty?
84
+ end
85
+ @response.body
86
+ rescue Faraday::Error::ClientError => e
87
+ handle_client_error e
88
+ rescue Faraday::Error::TimeoutError, Timeout::Error => e
89
+ raise e
90
+ ensure
91
+ @request = nil
92
+ end
93
+
94
+ private
95
+
96
+ def method_missing(symbol, *args)
97
+ @request.send(symbol, *args) and self
98
+ rescue NoMethodError => e
99
+ raise e
100
+ end
101
+
102
+ def api_url(version)
103
+ "http://api.iactionable.com/v#{version}/"
104
+ end
105
+
106
+ def handle_client_error(e)
107
+ # http://iactionable.com/api/response-codes/
108
+ case e.response[:status]
109
+ when 400
110
+ raise IActionable::Error::BadRequest.new(e.response)
111
+ when 401
112
+ raise IActionable::Error::Unauthorized.new(e.response)
113
+ when 500
114
+ raise IActionable::Error::Internal.new(e.response)
115
+ end
116
+ end
117
+ end
118
+ end