Class: IMS::LTI::OutcomeRequest

Inherits:
ToolBase
  • Object
show all
Includes:
Extensions::Base
Defined in:
lib/ims/lti/outcome_request.rb

Overview

Class for consuming/generating LTI Outcome Requests

Outcome Request documentation: www.imsglobal.org/lti/v1p1pd/ltiIMGv1p1pd.html#_Toc309649691

This class can be used by both Tool Providers and Tool Consumers. Each will use it a bit differently. The Tool Provider will use it to POST an OAuth-signed request to a TC. A Tool Consumer will use it to parse such a request from a TP.

Tool Provider Usage

An OutcomeRequest will generally be created through a configured ToolProvider object. See the ToolProvider documentation.

Tool Consumer Usage

When an outcome request is sent from a TP the body of the request is XML. This class parses that XML and provides a simple interface for accessing the information in the request. Typical usage would be:

# create an OutcomeRequest from the request object
req = IMS::LTI::OutcomeRequest.from_post_request(request)

# access the source id to identify the user who's grade you'd like to access
req.lis_result_sourcedid

# process the request
if req.replace_request?
  # set a new score for the user
elsif req.read_request?
  # return the score for the user
elsif req.delete_request?
  # clear the score for the user
else
  # return an unsupported OutcomeResponse
end

Constant Summary collapse

REPLACE_REQUEST =
'replaceResult'
DELETE_REQUEST =
'deleteResult'
READ_REQUEST =
'readResult'

Constants included from LaunchParams

LaunchParams::LAUNCH_DATA_PARAMETERS

Instance Attribute Summary collapse

Attributes included from RequestValidator

#oauth_signature_validator

Attributes included from LaunchParams

#custom_params, #ext_params, #non_spec_params

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Extensions::Base

#extend_outcome_request, #extend_outcome_response, #outcome_request_extensions, #outcome_response_extensions

Methods inherited from ToolBase

#post_service_request

Methods included from RequestValidator

#request_oauth_nonce, #request_oauth_timestamp, #valid_request!, #valid_request?

Methods included from LaunchParams

#get_custom_param, #get_ext_param, #get_non_spec_param, #process_params, #roles=, #set_custom_param, #set_ext_param, #set_non_spec_param, #to_params

Constructor Details

#initialize(opts = {}) ⇒ OutcomeRequest

Create a new OutcomeRequest

Parameters:

  • opts (Hash) (defaults to: {})

    initialization hash



49
50
51
52
53
# File 'lib/ims/lti/outcome_request.rb', line 49

def initialize(opts={})
  opts.each_pair do |key, val|
    self.send("#{key}=", val) if self.respond_to?("#{key}=")
  end
end

Instance Attribute Details

#consumer_keyObject

Returns the value of attribute consumer_key.



42
43
44
# File 'lib/ims/lti/outcome_request.rb', line 42

def consumer_key
  @consumer_key
end

#consumer_secretObject

Returns the value of attribute consumer_secret.



42
43
44
# File 'lib/ims/lti/outcome_request.rb', line 42

def consumer_secret
  @consumer_secret
end

#lis_outcome_service_urlObject

Returns the value of attribute lis_outcome_service_url.



42
43
44
# File 'lib/ims/lti/outcome_request.rb', line 42

def lis_outcome_service_url
  @lis_outcome_service_url
end

#lis_result_sourcedidObject

Returns the value of attribute lis_result_sourcedid.



42
43
44
# File 'lib/ims/lti/outcome_request.rb', line 42

def lis_result_sourcedid
  @lis_result_sourcedid
end

#message_identifierObject

Returns the value of attribute message_identifier.



42
43
44
# File 'lib/ims/lti/outcome_request.rb', line 42

def message_identifier
  @message_identifier
end

#operationObject

Returns the value of attribute operation.



42
43
44
# File 'lib/ims/lti/outcome_request.rb', line 42

def operation
  @operation
end

#outcome_responseObject

Returns the value of attribute outcome_response.



42
43
44
# File 'lib/ims/lti/outcome_request.rb', line 42

def outcome_response
  @outcome_response
end

#post_requestObject

Returns the value of attribute post_request.



42
43
44
# File 'lib/ims/lti/outcome_request.rb', line 42

def post_request
  @post_request
end

#scoreObject

Returns the value of attribute score.



42
43
44
# File 'lib/ims/lti/outcome_request.rb', line 42

def score
  @score
end

Class Method Details

.from_post_request(post_request) ⇒ Object

Convenience method for creating a new OutcomeRequest from a request object

req = IMS::LTI::OutcomeRequest.from_post_request(request)


58
59
60
61
# File 'lib/ims/lti/outcome_request.rb', line 58

def self.from_post_request(post_request)
  request = OutcomeRequest.new
  request.process_post_request(post_request)
end

Instance Method Details

#delete_request?Boolean

Check whether this request is a deleteResult request

Returns:

  • (Boolean)


106
107
108
# File 'lib/ims/lti/outcome_request.rb', line 106

def delete_request?
  @operation == DELETE_REQUEST
end

#generate_request_xmlObject



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/ims/lti/outcome_request.rb', line 151

def generate_request_xml
  raise IMS::LTI::InvalidLTIConfigError, "`@operation` and `@lis_result_sourcedid` are required" unless has_request_xml_attributes?
  builder = Builder::XmlMarkup.new #(:indent=>2)
  builder.instruct!

  builder.imsx_POXEnvelopeRequest("xmlns" => "http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0") do |env|
    env.imsx_POXHeader do |header|
      header.imsx_POXRequestHeaderInfo do |info|
        info.imsx_version "V1.0"
        info.imsx_messageIdentifier @message_identifier || IMS::LTI::generate_identifier
      end
    end
    env.imsx_POXBody do |body|
      body.tag!(@operation + 'Request') do |request|
        request.resultRecord do |record|
          record.sourcedGUID do |guid|
            guid.sourcedId @lis_result_sourcedid
          end
          results(record)
        end
        submission_details(request)
      end
    end
  end
end

#outcome_post_successful?Boolean

Check whether the last outcome POST was successful

Returns:

  • (Boolean)


116
117
118
# File 'lib/ims/lti/outcome_request.rb', line 116

def outcome_post_successful?
  @outcome_response && @outcome_response.success?
end

#post_delete_result!OutcomeResponse

POSTs a deleteResult to the Tool Consumer

Returns:



87
88
89
90
# File 'lib/ims/lti/outcome_request.rb', line 87

def post_delete_result!
  @operation = DELETE_REQUEST
  post_outcome_request
end

#post_outcome_requestOutcomeResponse

POST an OAuth signed request to the Tool Consumer

Returns:

Raises:



123
124
125
126
127
128
129
130
131
132
# File 'lib/ims/lti/outcome_request.rb', line 123

def post_outcome_request
  raise IMS::LTI::InvalidLTIConfigError, "" unless has_required_attributes?

  res = post_service_request(@lis_outcome_service_url,
                             'application/xml',
                             generate_request_xml)

  @outcome_response = extend_outcome_response(OutcomeResponse.new)
  @outcome_response.process_post_response(res)
end

#post_read_result!OutcomeResponse

POSTs a readResult to the Tool Consumer

Returns:



95
96
97
98
# File 'lib/ims/lti/outcome_request.rb', line 95

def post_read_result!
  @operation = READ_REQUEST
  post_outcome_request
end

#post_replace_result!(score) ⇒ OutcomeResponse

POSTs the given score to the Tool Consumer with a replaceResult

Returns:



78
79
80
81
82
# File 'lib/ims/lti/outcome_request.rb', line 78

def post_replace_result!(score)
  @operation = REPLACE_REQUEST
  @score = score
  post_outcome_request
end

#process_post_request(post_request) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/ims/lti/outcome_request.rb', line 63

def process_post_request(post_request)
  self.post_request = post_request
  if post_request.body.respond_to?(:read)
    xml = post_request.body.read
    post_request.body.rewind
  else
    xml = post_request.body
  end
  self.process_xml(xml)
  self
end

#process_xml(xml) ⇒ Object

Parse Outcome Request data from XML



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/ims/lti/outcome_request.rb', line 135

def process_xml(xml)
  doc = REXML::Document.new xml
  @message_identifier = doc.text("//imsx_POXRequestHeaderInfo/imsx_messageIdentifier")
  @lis_result_sourcedid = doc.text("//resultRecord/sourcedGUID/sourcedId")

  if REXML::XPath.first(doc, "//deleteResultRequest")
    @operation = DELETE_REQUEST
  elsif REXML::XPath.first(doc, "//readResultRequest")
    @operation = READ_REQUEST
  elsif REXML::XPath.first(doc, "//replaceResultRequest")
    @operation = REPLACE_REQUEST
    @score = doc.get_text("//resultRecord/result/resultScore/textString")
  end
  extention_process_xml(doc)
end

#read_request?Boolean

Check whether this request is a readResult request

Returns:

  • (Boolean)


111
112
113
# File 'lib/ims/lti/outcome_request.rb', line 111

def read_request?
  @operation == READ_REQUEST
end

#replace_request?Boolean

Check whether this request is a replaceResult request

Returns:

  • (Boolean)


101
102
103
# File 'lib/ims/lti/outcome_request.rb', line 101

def replace_request?
  @operation == REPLACE_REQUEST
end