ruby-iactionable 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.gitignore +4 -0
  2. data/.rvmrc +3 -0
  3. data/CHANGELOG.md +5 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +43 -0
  6. data/README.md +49 -0
  7. data/Rakefile +1 -0
  8. data/lib/iactionable/api.rb +170 -0
  9. data/lib/iactionable/connection.rb +114 -0
  10. data/lib/iactionable/error.rb +17 -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 +36 -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/objects.rb +27 -0
  31. data/lib/iactionable/settings.rb +30 -0
  32. data/lib/iactionable/version.rb +3 -0
  33. data/lib/iactionable.rb +9 -0
  34. data/ruby_iactionable.gemspec +28 -0
  35. data/spec/api/get_achievements_api_response_spec.rb +46 -0
  36. data/spec/api/get_challenges_api_response_spec.rb +42 -0
  37. data/spec/api/get_goals_api_response_spec.rb +46 -0
  38. data/spec/api/get_leaderboard_api_response_spec.rb +76 -0
  39. data/spec/api/get_profile_achievements_api_response_spec.rb +99 -0
  40. data/spec/api/get_profile_api_response_spec.rb +103 -0
  41. data/spec/api/get_profile_challenges_api_response_spec.rb +85 -0
  42. data/spec/api/get_profile_goals_api_response_spec.rb +89 -0
  43. data/spec/api/get_profile_notifications_api_response_spec.rb +75 -0
  44. data/spec/api/get_profile_points_api_response_spec.rb +67 -0
  45. data/spec/api_spec.rb +314 -0
  46. data/spec/connection_spec.rb +111 -0
  47. data/spec/settings_spec.rb +52 -0
  48. data/spec/spec_helper.rb +1 -0
  49. metadata +163 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ .bundle
3
+ .DS_Store
4
+ .rvmrc
data/.rvmrc ADDED
@@ -0,0 +1,3 @@
1
+ rvm_gemset_create_on_use_flag=1
2
+ rvm use ruby-1.9.2-p136@ruby_iactionable
3
+ rvm wrapper ruby-1.9.2-p136@ruby_iactionable textmate
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # CHANGELOG #
2
+
3
+ ## 0.0.1 ##
4
+
5
+ * 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,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ Ruby IActionable (0.0.1)
5
+ activesupport (>= 3.0.0)
6
+ faraday
7
+ faraday-stack
8
+ rake
9
+
10
+ GEM
11
+ remote: http://rubygems.org/
12
+ specs:
13
+ activesupport (3.2.1)
14
+ i18n (~> 0.6)
15
+ multi_json (~> 1.0)
16
+ addressable (2.2.6)
17
+ diff-lcs (1.1.3)
18
+ faraday (0.7.6)
19
+ addressable (~> 2.2)
20
+ multipart-post (~> 1.1)
21
+ rack (~> 1.1)
22
+ faraday-stack (0.1.5)
23
+ faraday (>= 0.6, < 0.8)
24
+ i18n (0.6.0)
25
+ multi_json (1.0.4)
26
+ multipart-post (1.1.4)
27
+ rack (1.4.1)
28
+ rake (0.9.2.2)
29
+ rspec (2.7.0)
30
+ rspec-core (~> 2.7.0)
31
+ rspec-expectations (~> 2.7.0)
32
+ rspec-mocks (~> 2.7.0)
33
+ rspec-core (2.7.1)
34
+ rspec-expectations (2.7.0)
35
+ diff-lcs (~> 1.1.2)
36
+ rspec-mocks (2.7.0)
37
+
38
+ PLATFORMS
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ Ruby IActionable!
43
+ rspec (>= 2.6)
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 'iactionable'
14
+
15
+ ## Bundler ##
16
+
17
+ gem 'ruby-iactionable', :require => '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/profiles/#getprofilesummary) 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,170 @@
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
+ @@settings = nil
10
+
11
+ def initialize
12
+ if @@settings
13
+ @connection = IActionable::Connection.new(@@settings)
14
+ else
15
+ raise IActionable::ConfigError.new("IActionable::Api cannot be initialized without credentials being set in IActionable::Api.init_settings()")
16
+ end
17
+ end
18
+
19
+ def self.init_settings(values)
20
+ @@settings = IActionable::Settings.new(values)
21
+ rescue IActionable::ConfigError => e
22
+ raise e
23
+ end
24
+
25
+ def self.settings
26
+ @@settings
27
+ end
28
+
29
+ # =================
30
+ # = Event Logging =
31
+ # =================
32
+
33
+ def log_event(profile_type, id_type, id, event_key, event_attrs = {})
34
+ response = @connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}/events/#{event_key}").with_params(event_attrs).post
35
+ end
36
+
37
+ # =====================
38
+ # = Profile API calls =
39
+ # =====================
40
+
41
+ def get_profile_summary(profile_type, id_type, id, achievement_count = nil)
42
+ request = @connection.request.with_app_key.to("/#{profile_type}/#{id_type}/#{id}")
43
+ request.with_params(:achievementCount => achievement_count) unless achievement_count.blank?
44
+ response = request.get
45
+ IActionable::Objects::ProfileSummary.new(response)
46
+ end
47
+
48
+ def create_profile(profile_type, id_type, id, display_name = nil)
49
+ request = @connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}")
50
+ request.with_params(:displayName => display_name) unless display_name.blank?
51
+ request.post
52
+ end
53
+ alias_method :update_profile, :create_profile
54
+
55
+ def add_profile_identifier(profile_type, id_type, id, alt_id_type, alt_id)
56
+ @connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}/identifiers/#{alt_id_type}/#{alt_id}").post
57
+ end
58
+
59
+ # ====================
60
+ # = Points API calls =
61
+ # ====================
62
+
63
+ def get_profile_points(profile_type, id_type, id, point_type)
64
+ response = @connection.request.with_app_key.to("/#{profile_type}/#{id_type}/#{id}/points/#{point_type}").get
65
+ IActionable::Objects::ProfilePoints.new(response)
66
+ end
67
+
68
+ def update_profile_points(profile_type, id_type, id, point_type, amount, reason = nil)
69
+ request = @connection.request.with_app_key.with_api_key.to("/#{profile_type}/#{id_type}/#{id}/points/#{point_type}").with_params(:value => amount)
70
+ request.with_params(:description => reason) unless reason.blank?
71
+ response = request.post
72
+ IActionable::Objects::ProfilePoints.new(response)
73
+ end
74
+
75
+ # =========================
76
+ # = Achievement API calls =
77
+ # =========================
78
+
79
+ def get_profile_achievements(profile_type, id_type, id, filter_type = nil)
80
+ request = @connection.request.with_app_key
81
+ case filter_type
82
+ when :completed
83
+ request.to("/#{profile_type}/#{id_type}/#{id}/achievements/Completed")
84
+ when :available
85
+ request.to("/#{profile_type}/#{id_type}/#{id}/achievements/Available")
86
+ else
87
+ request.to("/#{profile_type}/#{id_type}/#{id}/achievements")
88
+ end
89
+ IActionable::Objects::ProfileAchievements.new(request.get)
90
+ end
91
+
92
+ def get_achievements()
93
+ response = @connection.request.with_app_key.to("/achievements").get
94
+ response.map{|achievement_json| IActionable::Objects::Achievement.new(achievement_json)}
95
+ rescue NoMethodError => e
96
+ []
97
+ end
98
+
99
+ # ========================
100
+ # = Challenges API calls =
101
+ # ========================
102
+
103
+ def get_profile_challenges(profile_type, id_type, id, filter_type = nil)
104
+ request = @connection.request.with_app_key
105
+ case filter_type
106
+ when :completed
107
+ request.to("/#{profile_type}/#{id_type}/#{id}/challenges/Completed")
108
+ when :available
109
+ request.to("/#{profile_type}/#{id_type}/#{id}/challenges/Available")
110
+ else
111
+ request.to("/#{profile_type}/#{id_type}/#{id}/challenges")
112
+ end
113
+ IActionable::Objects::ProfileChallenges.new(request.get)
114
+ end
115
+
116
+ def get_challenges()
117
+ response = @connection.request.with_app_key.to("/challenges").get
118
+ response.map{|challenge_json| IActionable::Objects::Challenge.new(challenge_json)}
119
+ rescue NoMethodError => e
120
+ []
121
+ end
122
+
123
+ # ===================
124
+ # = Goals API calls =
125
+ # ===================
126
+
127
+ def get_profile_goals(profile_type, id_type, id, filter_type = nil)
128
+ request = @connection.request.with_app_key
129
+ case filter_type
130
+ when :completed
131
+ request.to("/#{profile_type}/#{id_type}/#{id}/goals/Completed")
132
+ when :available
133
+ request.to("/#{profile_type}/#{id_type}/#{id}/goals/Available")
134
+ else
135
+ request.to("/#{profile_type}/#{id_type}/#{id}/goals")
136
+ end
137
+ IActionable::Objects::ProfileGoals.new(request.get)
138
+ end
139
+
140
+ def get_goals()
141
+ response = @connection.request.with_app_key.to("/goals").get
142
+ response.map{|goal_json| IActionable::Objects::Goal.new(goal_json)}
143
+ rescue NoMethodError => e
144
+ []
145
+ end
146
+
147
+ # =========================
148
+ # = Leaderboard API calls =
149
+ # =========================
150
+
151
+ def get_leaderboard(profile_type, point_type, leaderboard, page_number=nil, page_count=nil, id=nil, id_type=nil)
152
+ request = @connection.request.with_app_key.to("/#{profile_type}/leaderboards/points/#{point_type}/#{leaderboard}")
153
+ request.with_params(:pageNumber => page_number) unless page_number.blank?
154
+ request.with_params(:pageCount => page_count) unless page_count.blank?
155
+ request.with_params(:id => id) unless id.blank? || id_type.blank?
156
+ request.with_params(:idType => id_type) unless id.blank? || id_type.blank?
157
+ response = request.get
158
+ IActionable::Objects::LeaderboardReport.new(response)
159
+ end
160
+
161
+ # ===================================
162
+ # = Profile Notifications API calls =
163
+ # ===================================
164
+
165
+ def get_profile_notifications(profile_type, id_type, id)
166
+ response = @connection.request.with_app_key.to("/#{profile_type}/#{id_type}/#{id}/notifications").get
167
+ IActionable::Objects::ProfileNotifications.new(response)
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,114 @@
1
+ require 'faraday'
2
+ require 'faraday_stack'
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 FaradayStack::ResponseJSON, 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
+ ensure
72
+ @request = nil
73
+ end
74
+
75
+ def post(path=nil, query_params={}, body_params={})
76
+ @request ||= Request.new(@settings)
77
+ @request.to(path).with_params(query_params)
78
+ @response = @connection.post do |req|
79
+ req.headers.merge! @request.headers
80
+ req.url @request.path, @request.params
81
+ req.body = @request.body unless @request.body.empty?
82
+ end
83
+ @response.body
84
+ rescue Exception => e
85
+ handle_client_error e
86
+ ensure
87
+ @request = nil
88
+ end
89
+
90
+ private
91
+
92
+ def method_missing(symbol, *args)
93
+ @request.send(symbol, *args) and self
94
+ rescue NoMethodError => e
95
+ raise e
96
+ end
97
+
98
+ def api_url(version)
99
+ "http://api.iactionable.com/v#{version}/"
100
+ end
101
+
102
+ def handle_client_error(e)
103
+ # http://iactionable.com/api/response-codes/
104
+ case e.response[:status]
105
+ when 400
106
+ raise IActionable::Error::BadRequest.new(e.response)
107
+ when 401
108
+ raise IActionable::Error::Unauthorized.new(e.response)
109
+ when 500
110
+ raise IActionable::Error::Internal.new(e.response)
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,17 @@
1
+ module IActionable
2
+ module Error
3
+ class Error < StandardError
4
+ attr_accessor :response
5
+
6
+ def initialize(response)
7
+ @response = response
8
+ super
9
+ end
10
+ end
11
+
12
+ # http://iactionable.com/api/response-codes/
13
+ class BadRequest < Error; end
14
+ class Unauthorized < Error; end
15
+ class Internal < Error; end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ module IActionable
2
+ module Objects
3
+ class Achievement < IActionableObject
4
+ attr_accessor :key
5
+ attr_accessor :description
6
+ attr_accessor :image_url
7
+ attr_accessor :name
8
+
9
+ def initialize(key_values={})
10
+ initialize_awardable(key_values)
11
+ super(key_values)
12
+ end
13
+
14
+ awardable
15
+
16
+ def to_hash
17
+ hash = {
18
+ "Key" => @key,
19
+ "Description" => @description,
20
+ "ImageURL" => @image_url,
21
+ "Name" => @name
22
+ }
23
+ hash.merge!(awardable_hash) unless @progress.empty?
24
+ hash.delete("AwardDate") if @award_date.nil?
25
+ hash
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,50 @@
1
+ module IActionable
2
+ module Objects
3
+ module Awardable
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def awardable
10
+ attr_accessor :award_date
11
+ attr_accessor :original_award_date
12
+ attr_accessor :progress
13
+ include IActionable::Objects::Awardable::InstanceMethods
14
+ end
15
+ end
16
+
17
+ module InstanceMethods
18
+ def initialize_awardable(key_values={})
19
+ @progress = extract_many_as(key_values, "Progress", IActionable::Objects::Progress)
20
+ # convert the miliseconds within the date string to seconds (per ruby)
21
+ # "/Date(1275706032317-0600)/" => "1275706032-0600"
22
+ @original_award_date = @award_date = key_values.delete("AwardDate")
23
+ @award_date = IActionableObject.timestamp_to_seconds(@award_date) unless @award_date.blank?
24
+ end
25
+
26
+ def complete?
27
+ @progress.any? && @progress.all?
28
+ end
29
+
30
+ def percent_complete
31
+ Integer(Float(@progress.select{|p| p.complete?}.size) / @progress.size * 100)
32
+ rescue TypeError => e
33
+ 0
34
+ end
35
+
36
+ def awarded_on
37
+ # bug in ruby 1.9.2 where Time.strptime does not support seconds-since-epoch format, but Date.strptime does, so we'll use that for now
38
+ Date.strptime(@award_date, "%s%z").to_time unless @award_date.blank?
39
+ end
40
+
41
+ def awardable_hash
42
+ {
43
+ "AwardDate" => @original_award_date,
44
+ "Progress" => @progress.map{|prog| prog.to_hash}
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,27 @@
1
+ module IActionable
2
+ module Objects
3
+ class Challenge < IActionableObject
4
+ awardable
5
+
6
+ attr_accessor :key
7
+ attr_accessor :description
8
+ attr_accessor :name
9
+
10
+ def initialize(key_values={})
11
+ initialize_awardable(key_values)
12
+ super(key_values)
13
+ end
14
+
15
+ def to_hash
16
+ hash = {
17
+ "Key" => @key,
18
+ "Description" => @description,
19
+ "Name" => @name
20
+ }
21
+ hash.merge!(awardable_hash) unless @progress.empty?
22
+ hash.delete("AwardDate") if @award_date.nil?
23
+ hash
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ module IActionable
2
+ module Objects
3
+ class Goal < IActionableObject
4
+ awardable
5
+
6
+ attr_accessor :key
7
+ attr_accessor :description
8
+ attr_accessor :name
9
+ attr_accessor :interval
10
+
11
+ def initialize(key_values={})
12
+ initialize_awardable(key_values)
13
+ super(key_values)
14
+ end
15
+
16
+ def to_hash
17
+ hash = {
18
+ "Key" => @key,
19
+ "Description" => @description,
20
+ "Name" => @name,
21
+ "Interval" => @interval
22
+ }
23
+ hash.merge!(awardable_hash) unless @progress.empty?
24
+ hash.delete("AwardDate") if @award_date.nil?
25
+ hash.delete("Interval") if @interval.nil?
26
+ hash
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,36 @@
1
+ module IActionable
2
+ module Objects
3
+ class IActionableObject
4
+ def initialize(key_values={})
5
+ key_values.each_pair do |key, value|
6
+ instance_variable_set "@#{key.camelize.underscore}".to_sym, value
7
+ end
8
+ end
9
+
10
+ def self.timestamp_regexp
11
+ /\/Date\((\d+)((\-|\+)\d{4})\)\//
12
+ end
13
+
14
+ def self.timestamp_to_seconds(timestamp)
15
+ milliseconds = timestamp[timestamp_regexp, 1]
16
+ tz = timestamp[timestamp_regexp, 2]
17
+ "#{Integer(milliseconds)/1000}#{tz}"
18
+ end
19
+
20
+ private
21
+
22
+ def extract_many_as(key_values, field, klass)
23
+ if key_values.fetch(field, nil).respond_to?(:inject)
24
+ loaded = []
25
+ content = key_values.delete(field)
26
+ content.each do |c|
27
+ loaded << klass.new(c)
28
+ end
29
+ loaded
30
+ else
31
+ []
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ module IActionable
2
+ module Objects
3
+ class Identifier < IActionableObject
4
+ attr_accessor :id
5
+ attr_accessor :id_hash
6
+ attr_accessor :id_type
7
+
8
+ def to_hash
9
+ {
10
+ "ID" => @id,
11
+ "IDHash" => @id_hash,
12
+ "IDType" => @id_type
13
+ }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module IActionable
2
+ module Objects
3
+ class Leaderboard < IActionableObject
4
+ attr_accessor :key
5
+ attr_accessor :name
6
+
7
+ def to_hash
8
+ {
9
+ "Key" => @key,
10
+ "Name" => @name
11
+ }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,30 @@
1
+ module IActionable
2
+ module Objects
3
+ class LeaderboardReport < IActionableObject
4
+ attr_accessor :page_count
5
+ attr_accessor :page_number
6
+ attr_accessor :total_count
7
+ attr_accessor :leaderboard
8
+ attr_accessor :point_type
9
+ attr_accessor :profiles
10
+
11
+ def initialize(key_values={})
12
+ @leaderboard = IActionable::Objects::PointType.new(key_values.delete("Leaderboard"))
13
+ @point_type = IActionable::Objects::PointType.new(key_values.delete("PointType"))
14
+ @profiles = extract_many_as(key_values, "Profiles", IActionable::Objects::ProfileSummary)
15
+ super(key_values)
16
+ end
17
+
18
+ def to_hash
19
+ {
20
+ "PageCount" => @page_count,
21
+ "PageNumber" => @page_number,
22
+ "TotalCount" => @total_count,
23
+ "Leaderboard" => @leaderboard.to_hash,
24
+ "PointType" => @point_type.to_hash,
25
+ "Profiles" => @profiles.map{|profile| profile.to_hash}
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,24 @@
1
+ module IActionable
2
+ module Objects
3
+ class Level < IActionableObject
4
+ attr_accessor :name
5
+ attr_accessor :number
6
+ attr_accessor :required_points
7
+ attr_accessor :level_type
8
+
9
+ def initialize(key_values={})
10
+ @level_type = IActionable::Objects::LevelType.new(key_values.delete("LevelType"))
11
+ super(key_values)
12
+ end
13
+
14
+ def to_hash
15
+ {
16
+ "Name" => @name,
17
+ "Number" => @number,
18
+ "RequiredPoints" => @required_points,
19
+ "LevelType" => @level_type.to_hash
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end