ims-lti 1.2.9 → 2.0.0.beta.1

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 (57) hide show
  1. checksums.yaml +5 -5
  2. data/Changelog.txt +0 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +15 -116
  5. data/lib/ims/lti/converters/time_json_converter.rb +13 -0
  6. data/lib/ims/lti/converters.rb +5 -0
  7. data/lib/ims/lti/models/base_url_choice.rb +15 -0
  8. data/lib/ims/lti/models/base_url_selector.rb +5 -0
  9. data/lib/ims/lti/models/contact.rb +5 -0
  10. data/lib/ims/lti/models/icon_endpoint.rb +5 -0
  11. data/lib/ims/lti/models/icon_info.rb +6 -0
  12. data/lib/ims/lti/models/localized_name.rb +11 -0
  13. data/lib/ims/lti/models/localized_text.rb +11 -0
  14. data/lib/ims/lti/models/lti_model.rb +169 -0
  15. data/lib/ims/lti/models/message_handler.rb +6 -0
  16. data/lib/ims/lti/models/messages/basic_lti_launch_request.rb +8 -0
  17. data/lib/ims/lti/models/messages/message.rb +43 -0
  18. data/lib/ims/lti/models/messages/registration_request.rb +17 -0
  19. data/lib/ims/lti/models/messages.rb +6 -0
  20. data/lib/ims/lti/models/parameter.rb +5 -0
  21. data/lib/ims/lti/models/product_family.rb +8 -0
  22. data/lib/ims/lti/models/product_info.rb +19 -0
  23. data/lib/ims/lti/models/product_instance.rb +10 -0
  24. data/lib/ims/lti/models/resource_handler.rb +18 -0
  25. data/lib/ims/lti/models/resource_type.rb +6 -0
  26. data/lib/ims/lti/models/rest_service.rb +14 -0
  27. data/lib/ims/lti/models/rest_service_profile.rb +7 -0
  28. data/lib/ims/lti/models/security_contract.rb +9 -0
  29. data/lib/ims/lti/models/service_owner.rb +8 -0
  30. data/lib/ims/lti/models/service_provider.rb +11 -0
  31. data/lib/ims/lti/models/tool_consumer_profile.rb +20 -0
  32. data/lib/ims/lti/models/tool_profile.rb +22 -0
  33. data/lib/ims/lti/models/tool_proxy.rb +11 -0
  34. data/lib/ims/lti/models/vendor.rb +28 -0
  35. data/lib/ims/lti/models.rb +29 -0
  36. data/lib/ims/lti/services/message_service.rb +40 -0
  37. data/lib/ims/lti/services.rb +5 -0
  38. data/lib/ims/lti/version.rb +1 -1
  39. data/lib/ims/lti.rb +6 -64
  40. data/lib/ims.rb +3 -1
  41. metadata +57 -50
  42. data/Changelog +0 -76
  43. data/LICENSE +0 -18
  44. data/lib/ims/lti/deprecated_role_checks.rb +0 -52
  45. data/lib/ims/lti/extensions/canvas.rb +0 -122
  46. data/lib/ims/lti/extensions/content.rb +0 -258
  47. data/lib/ims/lti/extensions/outcome_data.rb +0 -240
  48. data/lib/ims/lti/extensions.rb +0 -45
  49. data/lib/ims/lti/launch_params.rb +0 -166
  50. data/lib/ims/lti/outcome_request.rb +0 -225
  51. data/lib/ims/lti/outcome_response.rb +0 -166
  52. data/lib/ims/lti/request_validator.rb +0 -56
  53. data/lib/ims/lti/role_checks.rb +0 -101
  54. data/lib/ims/lti/tool_base.rb +0 -29
  55. data/lib/ims/lti/tool_config.rb +0 -231
  56. data/lib/ims/lti/tool_consumer.rb +0 -86
  57. data/lib/ims/lti/tool_provider.rb +0 -145
@@ -1,122 +0,0 @@
1
- module IMS::LTI
2
- module Extensions
3
- # Module that adds Canvas specific LTI extensions
4
- #
5
- # It adds convenience methods for generating common canvas use case LTI configurations
6
- #
7
- # == Usage
8
- # To generate an XML configuration:
9
- #
10
- # # Create a config object and set some options
11
- # tc = IMS::LTI::ToolConfig.new(:title => "Example Sinatra Tool Provider", :launch_url => url)
12
- # tc.description = "This example LTI Tool Provider supports LIS Outcome pass-back."
13
- #
14
- # # Extend the Canvas Tool config and add canvas related extensions
15
- # tc.extend IMS::LTI::Extensions::Canvas::ToolConfig
16
- # tc.homework_submission! 'http://someplace.com/homework', 'Find Homework'
17
- #
18
- # # generate the XML
19
- # tc.to_xml
20
- #
21
- # Or to create a config object from an XML String:
22
- #
23
- # tc = IMS::LTI::ToolConfig.create_from_xml(xml)
24
-
25
- module Canvas
26
- module ToolConfig
27
- PLATFORM = 'canvas.instructure.com'
28
-
29
- # Canvas extension defaults
30
- # These properties will cascade down to any options that are configured
31
- def set_canvas_ext_param(key, value)
32
- set_ext_param(PLATFORM, key, value)
33
- end
34
-
35
- def get_canvas_param(param_key)
36
- get_ext_param PLATFORM, param_key
37
- end
38
-
39
- def canvas_privacy_public!()
40
- set_canvas_ext_param(:privacy_level, 'public')
41
- end
42
-
43
- def canvas_privacy_name_only!()
44
- set_canvas_ext_param(:privacy_level, 'name_only')
45
- end
46
-
47
- def canvas_privacy_anonymous!()
48
- set_canvas_ext_param(:privacy_level, 'anonymous')
49
- end
50
-
51
- def canvas_domain!(domain)
52
- set_canvas_ext_param(:domain, domain)
53
- end
54
-
55
- def canvas_text!(text)
56
- set_canvas_ext_param(:text, text)
57
- end
58
-
59
- def canvas_icon_url!(icon_url)
60
- set_canvas_ext_param(:icon_url, icon_url)
61
- end
62
-
63
- def canvas_tool_id!(tool_id)
64
- set_canvas_ext_param(:tool_id, tool_id)
65
- end
66
-
67
- def canvas_selector_dimensions!(width, height)
68
- set_canvas_ext_param(:selection_width, width)
69
- set_canvas_ext_param(:selection_height, height)
70
- end
71
-
72
- # Canvas options
73
- # These configure canvas to expose the tool in various locations. Any properties that are set
74
- # at this level will override the defaults for this launch of the tool
75
-
76
- # Enables homework submissions via the tool
77
- # Valid properties are url, text, selection_width, selection_height, enabled
78
- def canvas_homework_submission!(params = {})
79
- set_canvas_ext_param(:homework_submission, params)
80
- end
81
-
82
- # Adds the tool to canvas' rich text editor
83
- # Valid properties are url, icon_url, text, selection_width, selection_height, enabled
84
- def canvas_editor_button!(params = {})
85
- set_canvas_ext_param(:editor_button, params)
86
- end
87
-
88
- # Adds the tool to canvas' resource selector
89
- # Valid properties are url, text, selection_width, selection_height, enabled
90
- def canvas_resource_selection!(params = {})
91
- set_canvas_ext_param(:resource_selection, params)
92
- end
93
-
94
- # Adds the tool to account level navigation in canvas
95
- # Valid properties are url, text, enabled
96
- def canvas_account_navigation!(params = {})
97
- set_canvas_ext_param(:account_navigation, params)
98
- end
99
-
100
- # Adds the tool to course level navigation in canvas
101
- # Valid properties are url, text, visibility, default, enabled
102
- # Visibility describes who will see the navigation element. Possible values are "admins", "members", and nil
103
- # Default determines if it is on or off by default. Possible values are "admins", "members", and nil
104
- def canvas_course_navigation!(params = {})
105
- set_canvas_ext_param(:course_navigation, params)
106
- end
107
-
108
- # Adds the tool to user level navigation in canvas
109
- # Valid properties are url, text, enabled
110
- def canvas_user_navigation!(params = {})
111
- set_canvas_ext_param(:user_navigation, params)
112
- end
113
-
114
- # Adds canvas environment configurations options
115
- # Valid properties are launch_url, domain, test_launch_url, test_domain, beta_launch_url, beta_domain
116
- def canvas_environments!(params = {})
117
- set_canvas_ext_param(:environments, params)
118
- end
119
- end
120
- end
121
- end
122
- end
@@ -1,258 +0,0 @@
1
- module IMS::LTI
2
- module Extensions
3
-
4
- # An LTI extension that adds support for content back to the consumer
5
- #
6
- # # Initialize TP object with OAuth creds and post parameters
7
- # provider = IMS::LTI::ToolProvider.new(consumer_key, consumer_secret, params)
8
- # # add extension
9
- # provider.extend IMS::LTI::Extensions::Content::ToolProvider
10
- #
11
- # If the tool was launched as an content request and it supports the content extension
12
- # you can redirect the user to the tool consumer using the return url helper methods.
13
- # The tool consumer is then responsible for consuming the content.
14
- #
15
- # #Check if a certain response type is available
16
- # if provider.accepts_url? do
17
- # #Generate the URL for the user
18
- # redirect provider.url_content_return_url(url)
19
- # end
20
- #
21
- module Content
22
- module ToolProvider
23
- include IMS::LTI::Extensions::ExtensionBase
24
- include Base
25
-
26
- # a list of the supported outcome data types
27
- def accepted_content_types
28
- return @content_types if @content_types
29
- @content_types = []
30
- if val = @ext_params["content_return_types"]
31
- @content_types = val.split(',').map {|i| i.to_sym}
32
- end
33
-
34
- @content_types
35
- end
36
-
37
- def accepted_file_extensions
38
- return @file_extensions if @file_extensions
39
- @file_extensions = []
40
- if val = @ext_params["content_file_extensions"]
41
- @file_extensions = val.split(',').map {|i| i.downcase.strip}
42
- end
43
-
44
- @file_extensions
45
- end
46
-
47
- def accepts_file?(file_name = nil)
48
- accepted_content_types.include?(:file) &&
49
- ( file_name.nil? ||
50
- accepted_file_extensions.empty? ||
51
- accepted_file_extensions.any?{|ext| file_name.downcase[/#{ext}$/]} )
52
- end
53
-
54
- def accepts_url?
55
- accepted_content_types.include?(:url)
56
- end
57
-
58
- def accepts_lti_launch_url?
59
- accepted_content_types.include?(:lti_launch_url)
60
- end
61
-
62
- def accepts_image_url?
63
- accepted_content_types.include?(:image_url)
64
- end
65
-
66
- def accepts_iframe?
67
- accepted_content_types.include?(:iframe)
68
- end
69
-
70
- def accepts_oembed?
71
- accepted_content_types.include?(:oembed)
72
- end
73
-
74
- def content_intended_use
75
- @ext_params["content_intended_use"].to_sym if @ext_params["content_intended_use"]
76
- end
77
-
78
- # check if the content extension is supported
79
- def accepts_content?
80
- !!@ext_params["content_return_types"]
81
- end
82
-
83
- # check if the consumer accepts a given type of content
84
- def accepts_content_type?(content_type)
85
- accepted_content_types.include? content_type.to_sym
86
- end
87
-
88
- #check the use of the content
89
- def is_content_for? (intended_use)
90
- content_intended_use == intended_use
91
- end
92
-
93
- def content_return_url
94
- @ext_params["content_return_url"]
95
- end
96
-
97
- #generates the return url for file submissions
98
- def file_content_return_url(url, text, content_type = nil)
99
-
100
- return_url = add_parameters(content_return_url, {
101
- return_type: 'file',
102
- url: url,
103
- text: text
104
- })
105
-
106
- if content_type
107
- return_url = add_parameters(return_url, {
108
- content_type: content_type
109
- })
110
- end
111
-
112
- return return_url
113
- end
114
-
115
- #generates the return url for url submissions
116
- def url_content_return_url(url, title = nil, text = 'link', target = '_blank')
117
-
118
- return_url = add_parameters(content_return_url, {
119
- return_type: 'url',
120
- url: url,
121
- text: text,
122
- target: target
123
- })
124
-
125
- if title
126
- return_url = add_parameters(return_url, {
127
- title:title
128
- })
129
- end
130
-
131
- return return_url
132
- end
133
-
134
- #generates the return url for lti launch submissions
135
- def lti_launch_content_return_url(url, text='link', title=nil)
136
-
137
- return_url = add_parameters(content_return_url, {
138
- return_type: 'lti_launch_url',
139
- url: url,
140
- text: text
141
- })
142
-
143
- if title
144
- return_url = add_parameters(return_url, {
145
- title:title
146
- })
147
- end
148
-
149
- return return_url
150
- end
151
-
152
- #generates the return url for image submissions
153
- def image_content_return_url(url, width, height, alt = '')
154
-
155
- add_parameters(content_return_url, {
156
- return_type: 'image_url',
157
- url: url,
158
- width: width.to_s,
159
- height: height.to_s,
160
- alt: alt
161
- })
162
- end
163
-
164
- #generates the return url for iframe submissions
165
- def iframe_content_return_url(url, width, height, title = nil)
166
-
167
- return_url = add_parameters(content_return_url, {
168
- return_type: 'iframe',
169
- url: url,
170
- width: width.to_s,
171
- height: height.to_s
172
- })
173
-
174
- if title
175
- return_url = add_parameters(return_url, {
176
- title:title
177
- })
178
- end
179
-
180
- return return_url
181
- end
182
-
183
- #generates the return url for oembed submissions
184
- def oembed_content_return_url(url, endpoint)
185
-
186
- add_parameters(content_return_url, {
187
- return_type: 'oembed',
188
- url: url,
189
- endpoint: endpoint
190
- })
191
- end
192
-
193
- private
194
-
195
- # adds parameters to a url, with consideration for
196
- # already existing parameters
197
- def add_parameters(url, params)
198
- parsed = URI.parse(url)
199
- query = if parsed.query
200
- CGI.parse(parsed.query)
201
- else
202
- {}
203
- end
204
-
205
- query = query.merge(params)
206
-
207
- parsed.query = URI.encode_www_form(query)
208
- parsed.to_s
209
- end
210
- end
211
-
212
- module ToolConsumer
213
- include IMS::LTI::Extensions::ExtensionBase
214
- include Base
215
-
216
- # a list of the content types accepted
217
- #
218
- # tc.add_content_return_types=(['url', 'text'])
219
- # tc.add_content_return_types=("url,text")
220
- def content_return_types=(val)
221
- val = val.join(',') if val.is_a? Array
222
- set_ext_param('content_return_types', val)
223
- end
224
-
225
- # a comma-separated string of the supported outcome data types
226
- def content_return_types
227
- get_ext_param('content_return_types')
228
- end
229
-
230
- def content_intended_use=(val)
231
- set_ext_param('content_intended_use', val)
232
- end
233
-
234
- def content_intended_use
235
- get_ext_param('content_intended_use')
236
- end
237
-
238
- # convenience method for setting support for homework content
239
- def support_homework_content!
240
- self.content_intended_use = 'homework'
241
- self.content_return_types = 'file,url'
242
- end
243
-
244
- # convenience method for setting support for embed content
245
- def support_embed_content!
246
- self.content_intended_use = 'embed'
247
- self.content_return_types = 'oembed,lti_launch_url,url,image_url,iframe'
248
- end
249
-
250
- # convenience method for setting support for navigation content
251
- def support_navigation_content!
252
- self.content_intended_use = 'navigation'
253
- self.content_return_types = 'lti_launch_url'
254
- end
255
- end
256
- end
257
- end
258
- end
@@ -1,240 +0,0 @@
1
- module IMS::LTI
2
- module Extensions
3
-
4
- # An LTI extension that adds support for sending data back to the consumer
5
- # in addition to the score.
6
- #
7
- # # Initialize TP object with OAuth creds and post parameters
8
- # provider = IMS::LTI::ToolProvider.new(consumer_key, consumer_secret, params)
9
- # # add extension
10
- # provider.extend IMS::LTI::Extensions::OutcomeData::ToolProvider
11
- #
12
- # If the tool was launch as an outcome service and it supports the data extension
13
- # you can POST a score to the TC.
14
- # The POST calls all return an OutcomeResponse object which can be used to
15
- # handle the response appropriately.
16
- #
17
- # # post the score to the TC, score should be a float >= 0.0 and <= 1.0
18
- # # this returns an OutcomeResponse object
19
- # if provider.accepts_outcome_text?
20
- # response = provider.post_extended_replace_result!(score: score, text: "submission text")
21
- # else
22
- # response = provider.post_replace_result!(score)
23
- # end
24
- # if response.success?
25
- # # grade write worked
26
- # elsif response.processing?
27
- # elsif response.unsupported?
28
- # else
29
- # # failed
30
- # end
31
- module OutcomeData
32
-
33
- #IMS::LTI::Extensions::OutcomeData::ToolProvider
34
- module Base
35
- def outcome_request_extensions
36
- super + [IMS::LTI::Extensions::OutcomeData::OutcomeRequest]
37
- end
38
- end
39
-
40
- module ToolProvider
41
- include IMS::LTI::Extensions::ExtensionBase
42
- include Base
43
-
44
- # a list of the supported outcome data types
45
- def accepted_outcome_types
46
- return @outcome_types if @outcome_types
47
- @outcome_types = []
48
- if val = @ext_params["outcome_data_values_accepted"]
49
- @outcome_types = val.split(',')
50
- end
51
-
52
- @outcome_types
53
- end
54
-
55
- # check if the outcome data extension is supported
56
- def accepts_outcome_data?
57
- !!@ext_params["outcome_data_values_accepted"]
58
- end
59
-
60
- # check if the consumer accepts text as outcome data
61
- def accepts_outcome_text?
62
- accepted_outcome_types.member?("text")
63
- end
64
-
65
- # check if the consumer accepts a url as outcome data
66
- def accepts_outcome_url?
67
- accepted_outcome_types.member?("url")
68
- end
69
-
70
- # check if the consumer accepts a submitted at date as outcome data
71
- def accepts_submitted_at?
72
- accepted_outcome_types.member?("submitted_at") ||
73
- @ext_params["ext_outcome_submission_submitted_at_accepted"] == "true"
74
- end
75
-
76
- def accepts_outcome_lti_launch_url?
77
- accepted_outcome_types.member?("lti_launch_url")
78
- end
79
-
80
- def accepts_outcome_result_total_score?
81
- !!@ext_params["outcome_result_total_score_accepted"]
82
- end
83
-
84
- def accepts_needs_additional_review?
85
- @ext_params["ext_outcome_submission_needs_additional_review_accepted"] == "true"
86
- end
87
-
88
- def accepts_prioritize_non_tool_grade?
89
- @ext_params["ext_outcome_submission_prioritize_non_tool_grade_accepted"] == "true"
90
- end
91
-
92
- # POSTs the given score to the Tool Consumer with a replaceResult and
93
- # adds the specified data.
94
- #
95
- # The data hash can have the keys "text", "cdata_text", "url", "submitted_at"
96
- # "needs_additional_review", "prioritize_non_tool_grade", or "lti_launch_url"
97
- #
98
- # If both cdata_text and text are sent, cdata_text will be used
99
- #
100
- # If score is nil, the replace result XML will not contain a resultScore node
101
- #
102
- # Creates a new OutcomeRequest object and stores it in @outcome_requests
103
- #
104
- # @return [OutcomeResponse] the response from the Tool Consumer
105
- # @deprecated Use #post_extended_replace_result! instead
106
- def post_replace_result_with_data!(score = nil, data={})
107
- data[:score] = score if score
108
- post_extended_replace_result!(data)
109
- end
110
-
111
- # POSTs the given score to the Tool Consumer with a replaceResult and
112
- # adds the specified data. The options hash can have the keys
113
- # :text, :cdata_text, :url, :submitted_at, :lti_launch_url, :score,
114
- # :needs_additional_review, or :total_score
115
- #
116
- # If both cdata_text and text are sent, cdata_text will be used
117
- # If both total_score and score are sent, total_score will be used
118
- # If score is nil, the replace result XML will not contain a resultScore node
119
- #
120
- # Creates a new OutcomeRequest object and stores it in @outcome_requests
121
- #
122
- # @return [OutcomeResponse] the response from the Tool Consumer
123
- def post_extended_replace_result!(options = {})
124
- opts = {}
125
- options.each {|k,v| opts[k.to_sym] = v}
126
-
127
- req = new_request
128
- req.outcome_cdata_text = opts[:cdata_text]
129
- req.outcome_text = opts[:text]
130
- req.outcome_url = opts[:url]
131
- req.submitted_at = opts[:submitted_at]
132
- req.needs_additional_review = opts[:needs_additional_review]
133
- req.prioritize_non_tool_grade = opts[:prioritize_non_tool_grade]
134
- req.outcome_lti_launch_url = opts[:lti_launch_url]
135
- req.total_score = opts[:total_score]
136
- req.post_replace_result!(opts[:score])
137
- end
138
- end
139
-
140
- module ToolConsumer
141
- include IMS::LTI::Extensions::ExtensionBase
142
- include Base
143
-
144
- OUTCOME_DATA_TYPES = %w{text url lti_launch_url submitted_at}
145
-
146
- # a list of the outcome data types accepted, currently only 'url', 'submitted_at' and
147
- # 'text' are valid
148
- #
149
- # tc.outcome_data_values_accepted(['url', 'text'])
150
- # tc.outcome_data_valued_accepted("url,text")
151
- def outcome_data_values_accepted=(val)
152
- if val.is_a? Array
153
- val = val.join(',')
154
- end
155
-
156
- set_ext_param('outcome_data_values_accepted', val)
157
- end
158
-
159
- # a comma-separated string of the supported outcome data types
160
- def outcome_data_values_accepted
161
- get_ext_param('outcome_data_values_accepted')
162
- end
163
-
164
- # convenience method for setting support for all current outcome data types
165
- def support_outcome_data!
166
- self.outcome_data_values_accepted = OUTCOME_DATA_TYPES
167
- end
168
- end
169
-
170
- module OutcomeRequest
171
- include IMS::LTI::Extensions::ExtensionBase
172
- include Base
173
-
174
- attr_accessor :outcome_text,
175
- :outcome_url,
176
- :submitted_at,
177
- :outcome_lti_launch_url,
178
- :outcome_cdata_text,
179
- :total_score,
180
- :needs_additional_review,
181
- :prioritize_non_tool_grade
182
-
183
- def result_values(node)
184
- super
185
-
186
- if total_score
187
- node.resultTotalScore do |res_total_score|
188
- res_total_score.language "en" # 'en' represents the format of the number
189
- res_total_score.textString total_score.to_s
190
- end
191
- end
192
-
193
- if outcome_text || outcome_url || outcome_cdata_text || outcome_lti_launch_url
194
- node.resultData do |res_data|
195
- if outcome_cdata_text
196
- res_data.text {
197
- res_data.cdata! outcome_cdata_text
198
- }
199
- elsif outcome_text
200
- res_data.text outcome_text
201
- elsif outcome_lti_launch_url
202
- res_data.ltiLaunchUrl outcome_lti_launch_url
203
- end
204
- res_data.url outcome_url if outcome_url
205
- end
206
- end
207
- end
208
-
209
- def details(node)
210
- super
211
- return unless has_details_data?
212
-
213
- node.submittedAt submitted_at if submitted_at
214
- node.needsAdditionalReview if needs_additional_review
215
- node.prioritizeNonToolGrade if prioritize_non_tool_grade
216
- end
217
-
218
- def score
219
- total_score ? nil : @score
220
- end
221
-
222
- def has_result_data?
223
- !!outcome_text || !!outcome_url || !!outcome_lti_launch_url || !!outcome_cdata_text || !!total_score || super
224
- end
225
-
226
- def has_details_data?
227
- !!submitted_at || !!needs_additional_review || !!prioritize_non_tool_grade
228
- end
229
-
230
- def extention_process_xml(doc)
231
- super
232
- @outcome_text = doc.get_text("//resultRecord/result/resultData/text")
233
- @outcome_url = doc.get_text("//resultRecord/result/resultData/url")
234
- @outcome_lti_launch_url = doc.get_text("//resultRecord/result/resultData/ltiLaunchUrl")
235
- end
236
- end
237
-
238
- end
239
- end
240
- end
@@ -1,45 +0,0 @@
1
-
2
- module IMS::LTI
3
- module Extensions
4
-
5
- # Base functionality for creating LTI extension modules
6
- # See the test for this class for a simple example of how to create an extension module
7
- module Base
8
- def outcome_request_extensions
9
- []
10
- end
11
-
12
- def outcome_response_extensions
13
- []
14
- end
15
-
16
- def extend_outcome_request(request)
17
- outcome_request_extensions.each do |ext|
18
- request.extend(ext)
19
- end
20
- request
21
- end
22
-
23
- def extend_outcome_response(response)
24
- outcome_response_extensions.each do |ext|
25
- response.extend(ext)
26
- end
27
- response
28
- end
29
- end
30
-
31
- module ExtensionBase
32
- def outcome_request_extensions
33
- super
34
- end
35
-
36
- def outcome_response_extensions
37
- super
38
- end
39
- end
40
- end
41
- end
42
-
43
- require 'ims/lti/extensions/outcome_data'
44
- require 'ims/lti/extensions/content'
45
- require 'ims/lti/extensions/canvas'