tin_can_api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +80 -0
  7. data/Rakefile +12 -0
  8. data/lib/tin_can_api/about.rb +15 -0
  9. data/lib/tin_can_api/activity.rb +41 -0
  10. data/lib/tin_can_api/activity_definition.rb +139 -0
  11. data/lib/tin_can_api/agent.rb +44 -0
  12. data/lib/tin_can_api/agent_account.rb +33 -0
  13. data/lib/tin_can_api/attachment.rb +64 -0
  14. data/lib/tin_can_api/client.rb +402 -0
  15. data/lib/tin_can_api/context.rb +54 -0
  16. data/lib/tin_can_api/context_activities.rb +102 -0
  17. data/lib/tin_can_api/documents/activity_profile_document.rb +15 -0
  18. data/lib/tin_can_api/documents/agent_profile_document.rb +15 -0
  19. data/lib/tin_can_api/documents/document.rb +20 -0
  20. data/lib/tin_can_api/documents/state_document.rb +15 -0
  21. data/lib/tin_can_api/enum.rb +42 -0
  22. data/lib/tin_can_api/errors.rb +9 -0
  23. data/lib/tin_can_api/group.rb +37 -0
  24. data/lib/tin_can_api/interaction_component.rb +32 -0
  25. data/lib/tin_can_api/interaction_type.rb +58 -0
  26. data/lib/tin_can_api/lrs_response.rb +14 -0
  27. data/lib/tin_can_api/query_result_format.rb +6 -0
  28. data/lib/tin_can_api/remote_lrs.rb +15 -0
  29. data/lib/tin_can_api/result.rb +45 -0
  30. data/lib/tin_can_api/score.rb +39 -0
  31. data/lib/tin_can_api/statement.rb +53 -0
  32. data/lib/tin_can_api/statement_ref.rb +31 -0
  33. data/lib/tin_can_api/statements/statements_base.rb +70 -0
  34. data/lib/tin_can_api/statements_query.rb +42 -0
  35. data/lib/tin_can_api/statements_query_v095.rb +42 -0
  36. data/lib/tin_can_api/statements_result.rb +17 -0
  37. data/lib/tin_can_api/sub_statement.rb +19 -0
  38. data/lib/tin_can_api/tcapi_version.rb +27 -0
  39. data/lib/tin_can_api/verb.rb +35 -0
  40. data/lib/tin_can_api/version.rb +4 -0
  41. data/lib/tin_can_api.rb +37 -0
  42. data/spec/fixtures/about.json +10 -0
  43. data/spec/fixtures/statement.json +33 -0
  44. data/spec/spec_helper.rb +106 -0
  45. data/spec/support/helpers.rb +43 -0
  46. data/spec/tin_can_api/activity_definition_spec.rb +37 -0
  47. data/spec/tin_can_api/activity_spec.rb +23 -0
  48. data/spec/tin_can_api/agent_account_spec.rb +13 -0
  49. data/spec/tin_can_api/agent_spec.rb +24 -0
  50. data/spec/tin_can_api/attachment_spec.rb +26 -0
  51. data/spec/tin_can_api/client_spec.rb +44 -0
  52. data/spec/tin_can_api/context_activities_spec.rb +57 -0
  53. data/spec/tin_can_api/context_spec.rb +32 -0
  54. data/spec/tin_can_api/group_spec.rb +15 -0
  55. data/spec/tin_can_api/interaction_component_spec.rb +18 -0
  56. data/spec/tin_can_api/result_spec.rb +26 -0
  57. data/spec/tin_can_api/score_spec.rb +12 -0
  58. data/spec/tin_can_api/statement_ref_spec.rb +19 -0
  59. data/spec/tin_can_api/statement_spec.rb +57 -0
  60. data/spec/tin_can_api/sub_statement_spec.rb +30 -0
  61. data/spec/tin_can_api/verb_spec.rb +17 -0
  62. data/tin_can_api.gemspec +30 -0
  63. metadata +238 -0
@@ -0,0 +1,402 @@
1
+ # encoding: utf-8
2
+ require 'faraday'
3
+ require 'addressable/uri'
4
+ require 'tin_can_api/tcapi_version'
5
+ module TinCanApi
6
+ # Class used to communicate with a TCAPI endpoint synchronously
7
+ class Client
8
+ include TinCanApi::TCAPIVersion
9
+
10
+ VALID_PARAMS = %w(end_point user_name password version)
11
+
12
+ attr_accessor :end_point, :user_name, :password, :version
13
+
14
+ def initialize(options={}, &block)
15
+ setup_options(options)
16
+ yield_or_eval(&block) if block_given?
17
+ @version ||= latest_version
18
+ end
19
+
20
+ def about
21
+ response = connection.get("#{path}about")
22
+ LrsResponse.new do |lrs|
23
+ lrs.status = response.status
24
+ if response.status== 200
25
+ lrs.content = About.new(json: response.body)
26
+ lrs.success = true
27
+ else
28
+ lrs.success = false
29
+ end
30
+ end
31
+ end
32
+
33
+ def save_statement(statement)
34
+ # TODO: Complete this
35
+ if statement.id
36
+ response = connection.put do |req|
37
+ req.url("#{path}statements")
38
+ req.headers['Content-Type'] = 'application/json'
39
+ req.params.merge!({'statementId' => statement.id})
40
+ req.body = statement.serialize(latest_version).to_json
41
+ end
42
+ else
43
+ response = connection.post do |req|
44
+ req.url("#{path}statements")
45
+ req.headers['Content-Type'] = 'application/json'
46
+ req.body = statement.serialize(latest_version).to_json
47
+ end
48
+ end
49
+ LrsResponse.new do |lrs|
50
+ lrs.status = response.status
51
+ lrs.content = statement
52
+ if response.status == 200
53
+ statement.id = JSON.parse(response.body).first
54
+ lrs.success = true
55
+ elsif response.status == 204
56
+ lrs.success = true
57
+ else
58
+ lrs.success = false
59
+ end
60
+ end
61
+ end
62
+
63
+ def save_statements(statements)
64
+ # TODO: Complete this
65
+ if statements.empty?
66
+ return LrsResponse.new do |lrs|
67
+ lrs.success = true
68
+ end
69
+ end
70
+ response = connection.post do |req|
71
+ req.url("#{path}statements")
72
+ req.headers['Content-Type'] = 'application/json'
73
+ req.body = statements.map {|s| s.serialize(latest_version)}.to_json
74
+ end
75
+ LrsResponse.new do |lrs|
76
+ lrs.status = response.status
77
+ if response.status == 200
78
+ lrs.content = statements
79
+ ids = JSON.parse(response.body)
80
+ statements.each_with_index do |statement, index|
81
+ statement.id = ids[index]
82
+ end
83
+ lrs.success = true
84
+ else
85
+ lrs.success = false
86
+ end
87
+ end
88
+ end
89
+
90
+ def retrieve_statement(id)
91
+ get_statement(id, 'statementId')
92
+ end
93
+
94
+ def retrieve_voided_statement(id)
95
+ param_name = version == TCAPIVersion.V095 ? 'statementId' : 'voidedStatementId'
96
+ get_statement(id, param_name)
97
+ end
98
+
99
+ def query_statements(statement_query)
100
+ # TODO: Complete this
101
+ query = statement_query
102
+ unless query
103
+ query = version == TCAPIVersion::V095 ? StatementsQueryV095.new : StatementsQuery.new
104
+ end
105
+ # Error if the query parameters don't match the LRS version
106
+ raise Errors::IncompatibleTCAPIVersion, "Attempted to issue #{version} query using a #{query.version} set of query parameters." unless version == query.version
107
+
108
+ response = connection.get do |req|
109
+ req.url("#{path}statements")
110
+ req.params.merge!(query.parameter_map)
111
+ end
112
+ LrsResponse.new do |lrs|
113
+ lrs.status = response.status
114
+ if response.status == 200
115
+ # TODO: FIX THIS
116
+ lrs.success = true
117
+ lrs.content = StatementsResult.new(json: response.body)
118
+ else
119
+ lrs.success = false
120
+ end
121
+ end
122
+ end
123
+
124
+ def more_statements(more_url)
125
+ # TODO: Complete this
126
+ # more_url is relative to the endpoint's server root
127
+ response = connection.get do |req|
128
+ req.url("#{path}#{more_url}")
129
+ end
130
+ LrsResponse.new do |lrs|
131
+ lrs.status = response.status
132
+ if response.status == 200
133
+ # TODO: FIX THIS
134
+ lrs.success = true
135
+ lrs.content = StatementsResult.new(json: response.body)
136
+ else
137
+ lrs.success = false
138
+ end
139
+ end
140
+ end
141
+
142
+ def retrieve_state_ids(activity, agent, registration)
143
+ # TODO: Complete this
144
+ query_params = {
145
+ 'activityId' => activity.id,
146
+ 'agent' => agent.serialize(version).to_json
147
+ }
148
+ query_params['registration'] = registration if registration
149
+ get_profile_keys('activities/state', query_params)
150
+ end
151
+
152
+ def retrieve_state(id, activity, agent, registration)
153
+ # TODO: Complete this
154
+ query_params = {
155
+ 'stateId' => id,
156
+ 'activityId' => activity.id,
157
+ 'agent' => agent.serialize(version).to_json
158
+ }
159
+ document = StateDocument.new do |sd|
160
+ sd.id = id
161
+ sd.activity = activity
162
+ sd.agent = agent
163
+ end
164
+ lrs_response = get_document('activities/state', query_params, document)
165
+ if lrs_response.status == 200
166
+ lrs_response.content = document
167
+ end
168
+ lrs_response
169
+ end
170
+
171
+ def save_state(state)
172
+ # TODO: Complete this
173
+ query_params = {
174
+ 'stateId' => state.id,
175
+ 'activityId' => state.activity.id,
176
+ 'agent' => state.agent.serialize(version).to_json
177
+ }
178
+ save_document('activities/state', query_params, state)
179
+ end
180
+
181
+ def delete_state(state)
182
+ # TODO: Complete this
183
+ query_params = {
184
+ 'stateId' => state.id,
185
+ 'activityId' => state.activity.id,
186
+ 'agent' => state.agent.serialize(version).to_json
187
+ }
188
+ query_params['registration'] = state.registration if state.registration
189
+ delete_document('activities/state', query_params)
190
+ end
191
+
192
+ def clear_state(activity, agent, registration)
193
+ # TODO: Complete this
194
+ query_params = {
195
+ 'activityId' => activity.id,
196
+ 'agent' => agent.serialize(version).to_json
197
+ }
198
+ query_params['registration'] = registration if registration
199
+ delete_document('activities/state', query_params)
200
+ end
201
+
202
+ def retrieve_activity_profile_ids(activity)
203
+ # TODO: Complete this
204
+ query_params = {
205
+ 'activityId' => activity.id
206
+ }
207
+ get_profile_keys('activities/profile', query_params)
208
+ end
209
+
210
+ def retrieve_activity_profile(id, activity)
211
+ # TODO: Complete this
212
+ query_params = {
213
+ 'profileId' => id,
214
+ 'activityId' => activity.id,
215
+ }
216
+ document = ActivityProfileDocument.new do |apd|
217
+ apd.id = id
218
+ apd.activity = activity
219
+ end
220
+ lrs_response = get_document('activities/profile', query_params, document)
221
+ if lrs_response.status == 200
222
+ lrs_response.content = document
223
+ end
224
+ lrs_response
225
+ end
226
+
227
+ def save_activity_profile(profile)
228
+ # TODO: Complete this
229
+ query_params = {
230
+ 'profileId' => profile.id,
231
+ 'activityId' => profile.activity.id,
232
+ }
233
+ save_document('activities/profile', query_params, profile)
234
+ end
235
+
236
+ def delete_activity_profile(profile)
237
+ # TODO: Complete this
238
+ query_params = {
239
+ 'profileId' => profile.id,
240
+ 'activityId' => profile.activity.id,
241
+ }
242
+ delete_document('activities/profile', query_params)
243
+ end
244
+
245
+ def retrieve_agent_profile_ids(agent)
246
+ # TODO: Complete this
247
+ query_params = {
248
+ 'agent' => agent.serialize(version).to_json
249
+ }
250
+ get_profile_keys('agents/profile', query_params)
251
+ end
252
+
253
+ def retrieve_agent_profile(id, agent)
254
+ # TODO: Complete this
255
+ query_params = {
256
+ 'profileId' => id,
257
+ 'agent' => agent.serialize(version).to_json
258
+ }
259
+ document = AgentProfileDocument.new do |apd|
260
+ apd.id = id
261
+ apd.agent = agent
262
+ end
263
+ lrs_response = get_document('agents/profile', query_params, document)
264
+ if lrs_response.status == 200
265
+ lrs_response.content = document
266
+ end
267
+ lrs_response
268
+ end
269
+
270
+ def save_agent_profile(profile)
271
+ # TODO: Complete this
272
+ query_params = {
273
+ 'profileId' => profile.id,
274
+ 'agent' => profile.agent.serialize(version).to_json
275
+ }
276
+ save_document('agents/profile', query_params, profile)
277
+ end
278
+
279
+ def delete_agent_profile(profile)
280
+ # TODO: Complete this
281
+ query_params = {
282
+ 'profileId' => profile.id,
283
+ 'agent' => profile.agent.serialize(version).to_json
284
+ }
285
+ delete_document('agents/profile', query_params)
286
+ end
287
+
288
+ private
289
+
290
+ def setup_options(options={})
291
+ options.each_pair do |key, value|
292
+ if value && VALID_PARAMS.include?(key.to_s)
293
+ instance_variable_set("@#{key}", value)
294
+ end
295
+ end
296
+ end
297
+
298
+ def yield_or_eval(&block)
299
+ return unless block
300
+ block.arity < 1 ? instance_eval(&block) : block[self]
301
+ end
302
+
303
+ def uri
304
+ @uri ||= Addressable::URI.parse(end_point)
305
+ end
306
+
307
+ def path
308
+ @path ||= uri.path
309
+ @path += '/' unless @path.end_with?('/')
310
+ @path
311
+ end
312
+
313
+ def connection
314
+ base_url = "#{uri.scheme}://#{uri.host}"
315
+ base_url = "#{base_url}:#{uri.port}" if uri.port
316
+ @connection ||= Faraday.new(:url => base_url) do |faraday|
317
+ faraday.request :url_encoded # form-encode POST params
318
+ faraday.response :logger # log requests to STDOUT
319
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
320
+ faraday.headers['X-Experience-API-Version'] = version.to_s
321
+ faraday.basic_auth(user_name, password)
322
+ end
323
+ end
324
+
325
+ def get_statement(id, parameter)
326
+ response = connection.get do |req|
327
+ req.url("#{path}statements")
328
+ req.headers['Content-Type'] = 'application/json'
329
+ req.params.merge!({parameter => id})
330
+ end
331
+ LrsResponse.new do |lrs|
332
+ lrs.status = response.status
333
+ if response.status== 200
334
+ lrs.content = Statement.new(json: response.body)
335
+ lrs.success = true
336
+ else
337
+ lrs.success = false
338
+ end
339
+ end
340
+ end
341
+
342
+ def get_document(resource, params, document)
343
+ response = connection.get do |req|
344
+ req.url("#{path}#{resource}")
345
+ req.params.merge!(params)
346
+ end
347
+ LrsResponse.new do |lrs|
348
+ lrs.status = response.status
349
+ if response.status == 200
350
+ lrs.success = true
351
+ # TODO FIX THIS
352
+ elsif response.status == 404
353
+ lrs.success = true
354
+ else
355
+ lrs.success = false
356
+ end
357
+ end
358
+ end
359
+
360
+ def delete_document(resource, params)
361
+ response = connection.delete do |req|
362
+ req.url("#{path}#{resource}")
363
+ req.params.merge!(params)
364
+ end
365
+ LrsResponse.new do |lrs|
366
+ lrs.status = response.status
367
+ if response.status == 204
368
+ lrs.success = true
369
+ else
370
+ lrs.success = false
371
+ end
372
+ end
373
+ end
374
+
375
+ def save_document(resource, params, document)
376
+ # TODO: Complete this
377
+ response = connection.put do |req|
378
+ req.url("#{path}#{resource}")
379
+ req.headers['Content-Type'] = 'application/json'
380
+ req.headers['If-Match'] = document.etag if document.etag
381
+ req.params.merge!(params)
382
+ req.body = document.content
383
+ end
384
+ LrsResponse.new do |lrs|
385
+ lrs.status = response.status
386
+ if response.status == 204
387
+ lrs.success = true
388
+ else
389
+ lrs.success = false
390
+ end
391
+ end
392
+ end
393
+
394
+ def get_profile_keys(resource, params)
395
+ # TODO FIX THIS
396
+ connection.get do |req|
397
+ req.url("#{path}#{resource}")
398
+ req.params.merge!(params)
399
+ end
400
+ end
401
+ end
402
+ end
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+ module TinCanApi
3
+ # Context Class Description
4
+ class Context
5
+
6
+ attr_accessor :registration, :instructor, :team, :context_activities, :revision
7
+ attr_accessor :platform, :language, :statement, :extensions
8
+
9
+ def initialize(options={}, &block)
10
+ json = options.fetch(:json, nil)
11
+ if json
12
+ attributes = JSON.parse(json)
13
+ self.registration = attributes['registration'] if attributes['registration']
14
+ self.instructor = TinCanApi::Agent.new(json: attributes['instructor'].to_json) if attributes['instructor']
15
+ self.team = TinCanApi::Agent.new(json: attributes['team'].to_json) if attributes['team']
16
+ self.context_activities = TinCanApi::ContextActivities.new(json: attributes['contextActivities'].to_json) if attributes['contextActivities']
17
+ self.revision = attributes['revision'] if attributes['revision']
18
+ self.platform = attributes['platform'] if attributes['platform']
19
+ self.language = attributes['language'] if attributes['language']
20
+ self.statement = TinCanApi::StatementRef.new(json: attributes['statement'].to_json) if attributes['statement']
21
+ self.extensions = attributes['extensions'] if attributes['extensions']
22
+ else
23
+ self.registration = options.fetch(:registration, nil)
24
+ self.instructor = options.fetch(:instructor, nil)
25
+ self.team = options.fetch(:team, nil)
26
+ self.context_activities = options.fetch(:context_activities, nil)
27
+ self.revision = options.fetch(:revision, nil)
28
+ self.platform = options.fetch(:platform, nil)
29
+ self.language = options.fetch(:language, nil)
30
+ self.extensions = options.fetch(:extensions, nil)
31
+
32
+ if block_given?
33
+ block[self]
34
+ end
35
+ end
36
+ end
37
+
38
+ def serialize(version)
39
+ node = {}
40
+ node['registration'] = registration if registration
41
+ node['instructor'] = instructor.serialize(version) if instructor
42
+ node['team'] = team.serialize(version) if team
43
+ node['contextActivities'] = context_activities.serialize(version) if context_activities
44
+ node['revision'] = revision if revision
45
+ node['platform'] = platform if platform
46
+ node['language'] = language if language
47
+ node['statement'] = statement.serialize(version) if statement
48
+ node['extensions'] = extensions if extensions
49
+
50
+ node
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+ module TinCanApi
3
+ # ContextActivities Model class
4
+ class ContextActivities
5
+
6
+ attr_accessor :parent, :grouping, :other, :category
7
+
8
+ def initialize(options={}, &block)
9
+ json = options.fetch(:json, nil)
10
+ if json
11
+ attributes = JSON.parse(json)
12
+ if attributes['parent']
13
+ if attributes['parent'].is_a?(Array)
14
+ self.parent = attributes['parent'].map {|element| Activity.new(json: element.to_json)}
15
+ else
16
+ self.parent = [Activity.new(json: attributes['parent'].to_json)]
17
+ end
18
+ end
19
+
20
+ if attributes['grouping']
21
+ if attributes['grouping'].is_a?(Array)
22
+ self.grouping = attributes['grouping'].map {|element| Activity.new(json: element.to_json)}
23
+ else
24
+ self.grouping = [Activity.new(json: attributes['grouping'].to_json)]
25
+ end
26
+ end
27
+
28
+ if attributes['other']
29
+ if attributes['other'].is_a?(Array)
30
+ self.other = attributes['other'].map {|element| Activity.new(json: element.to_json)}
31
+ else
32
+ self.other = [Activity.new(json: attributes['other'].to_json)]
33
+ end
34
+ end
35
+
36
+ if attributes['category']
37
+ if attributes['category'].is_a?(Array)
38
+ self.category = attributes['category'].map {|element| Activity.new(json: element.to_json)}
39
+ else
40
+ self.category = [Activity.new(json: attributes['category'].to_json)]
41
+ end
42
+ end
43
+ else
44
+ self.parent = options.fetch(:parent, nil)
45
+ self.grouping = options.fetch(:grouping, nil)
46
+ self.other = options.fetch(:other, nil)
47
+ self.category = options.fetch(:category, nil)
48
+
49
+ if block_given?
50
+ block[self]
51
+ end
52
+ end
53
+ end
54
+
55
+ def serialize(version)
56
+ node = {}
57
+ if parent && parent.any?
58
+ if version == TinCanApi::TCAPIVersion::V095 && parent.size > 1
59
+ raise TinCanApi::Errors::IncompatibleTCAPIVersion, "Version #{version.to_s} doesn't support lists of activities (parent)"
60
+ end
61
+ if version == TinCanApi::TCAPIVersion::V095
62
+ node['parent'] = parent.first.serialize(version)
63
+ else
64
+ node['parent'] = parent.map {|element| element.serialize(version)}
65
+ end
66
+ end
67
+
68
+ if grouping && grouping.any?
69
+ if version == TinCanApi::TCAPIVersion::V095 && grouping.size > 1
70
+ raise TinCanApi::Errors::IncompatibleTCAPIVersion, "Version #{version.to_s} doesn't support lists of activities (grouping)"
71
+ end
72
+ if version == TinCanApi::TCAPIVersion::V095
73
+ node['grouping'] = grouping.first.serialize(version)
74
+ else
75
+ node['grouping'] = grouping.map {|element| element.serialize(version)}
76
+ end
77
+ end
78
+
79
+ if other && other.any?
80
+ if version == TinCanApi::TCAPIVersion::V095 && other.size > 1
81
+ raise TinCanApi::Errors::IncompatibleTCAPIVersion, "Version #{version.to_s} doesn't support lists of activities (other)"
82
+ end
83
+ if version == TinCanApi::TCAPIVersion::V095
84
+ node['other'] = other.first.serialize(version)
85
+ else
86
+ node['other'] = other.map {|element| element.serialize(version)}
87
+ end
88
+ end
89
+
90
+ if category && category.any?
91
+ if version.ordinal <= TinCanApi::TCAPIVersion::V100.ordinal
92
+ node['category'] = category.map {|element| element.serialize(version)}
93
+ else
94
+ raise TinCanApi::Errors::IncompatibleTCAPIVersion, "Version #{version.to_s} doesn't support the category context activity"
95
+ end
96
+ end
97
+
98
+ node
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ module TinCanApi
3
+ module Documents
4
+ class ActivityProfileDocument < Document
5
+
6
+ attr_accessor :activity
7
+
8
+ def initialize(&block)
9
+ super(&block)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ module TinCanApi
3
+ module Documents
4
+ class AgentProfileDocument < Document
5
+
6
+ attr_accessor :agent
7
+
8
+ def initialize(&block)
9
+ super(&block)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ module TinCanApi
3
+ module Documents
4
+ class Document
5
+
6
+ attr_accessor :id, :etag, :timestamp, :content_type, :content
7
+
8
+ def initialize(&block)
9
+ if block_given?
10
+ block[self]
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+
18
+ require_relative 'activity_profile_document'
19
+ require_relative 'agent_profile_document'
20
+ require_relative 'state_document'
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ module TinCanApi
3
+ module Documents
4
+ class StateDocument < Document
5
+
6
+ attr_accessor :activity, :agent, :registration
7
+
8
+ def initialize(&block)
9
+ super(&block)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ module TinCanApi
3
+ module Enum
4
+ CONVERT_PROC = Proc.new do
5
+ @values = constants.collect{|c| const_get(c)}.freeze
6
+
7
+ @values.each_with_index do |value, idx|
8
+ the_symbol = constants.find{|c| const_get(c) == value}
9
+ sig = class << value ; self end
10
+ sig.send :define_method, :name, proc{the_symbol}
11
+ sig.send :define_method, :ordinal, proc{idx}
12
+
13
+ if value.is_a? Hash
14
+ value.each do |k, v|
15
+ sig.send :define_method, k, (v.is_a?(Proc) ? v : proc{v})
16
+ end
17
+ end
18
+ value.freeze
19
+ end
20
+
21
+ class << self
22
+ alias :value_of :const_get
23
+ end
24
+
25
+ module_function
26
+ def each
27
+ @values.each { |v| yield v }
28
+ end
29
+ def values
30
+ @values
31
+ end
32
+ extend Enumerable
33
+
34
+ freeze
35
+ end
36
+
37
+ def self.extended extending_obj
38
+ extending_obj.module_eval &CONVERT_PROC
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+ module TinCanApi
3
+ module Errors
4
+
5
+ # Raised when an incompatible version is used
6
+ IncompatibleTCAPIVersion = Class.new(StandardError)
7
+
8
+ end
9
+ end