class AJIMS::LTI::OutcomeRequest
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
Constants
- DELETE_REQUEST
- READ_REQUEST
- REPLACE_REQUEST
Attributes
Public Class Methods
Convenience method for creating a new OutcomeRequest
from a request object
req = IMS::LTI::OutcomeRequest.from_post_request(request)
# File lib/ajims/lti/outcome_request.rb, line 58 def self.from_post_request(post_request) request = OutcomeRequest.new request.process_post_request(post_request) end
Create a new OutcomeRequest
@param opts [Hash] initialization hash
# File lib/ajims/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
Public Instance Methods
Check whether this request is a deleteResult request
# File lib/ajims/lti/outcome_request.rb, line 108 def delete_request? @operation == DELETE_REQUEST end
Check whether the last outcome POST was successful
# File lib/ajims/lti/outcome_request.rb, line 118 def outcome_post_successful? @outcome_response && @outcome_response.success? end
POSTs a deleteResult to the Tool Consumer
@return [OutcomeResponse] The response from the Tool Consumer
# File lib/ajims/lti/outcome_request.rb, line 89 def post_delete_result! @operation = DELETE_REQUEST post_outcome_request end
POST an OAuth signed request to the Tool Consumer
@return [OutcomeResponse] The response from the Tool Consumer
# File lib/ajims/lti/outcome_request.rb, line 125 def post_outcome_request raise AJIMS::LTI::InvalidLTIConfigError, "" unless has_required_attributes? consumer = OAuth::Consumer.new(@consumer_key, @consumer_secret) token = OAuth::AccessToken.new(consumer) res = token.post( @lis_outcome_service_url, generate_request_xml, 'Content-Type' => 'application/xml' ) @outcome_response = extend_outcome_response(OutcomeResponse.new) @outcome_response.process_post_response(res) end
POSTs a readResult to the Tool Consumer
@return [OutcomeResponse] The response from the Tool Consumer
# File lib/ajims/lti/outcome_request.rb, line 97 def post_read_result! @operation = READ_REQUEST post_outcome_request end
POSTs the given score to the Tool Consumer with a replaceResult
@return [OutcomeResponse] The response from the Tool Consumer
# File lib/ajims/lti/outcome_request.rb, line 78 def post_replace_result!(score, submitted_at: nil) @operation = REPLACE_REQUEST @score = score @submitted_at = submitted_at post_outcome_request end
# File lib/ajims/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
Parse Outcome Request data from XML
# File lib/ajims/lti/outcome_request.rb, line 142 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
Check whether this request is a readResult request
# File lib/ajims/lti/outcome_request.rb, line 113 def read_request? @operation == READ_REQUEST end
Check whether this request is a replaceResult request
# File lib/ajims/lti/outcome_request.rb, line 103 def replace_request? @operation == REPLACE_REQUEST end
Private Instance Methods
# File lib/ajims/lti/outcome_request.rb, line 160 def extention_process_xml(doc) end
# File lib/ajims/lti/outcome_request.rb, line 198 def generate_request_xml builder = Builder::XmlMarkup.new #(:indent=>2) builder.instruct! builder.imsx_POXEnvelopeRequest("xmlns" => "http://www.imsglobal.org/lis/oms1p0/pox") do |env| env.imsx_POXHeader do |header| header.imsx_POXRequestHeaderInfo do |info| info.imsx_version "V1.0" info.imsx_messageIdentifier @message_identifier || AJIMS::LTI::generate_identifier end end env.imsx_POXBody do |body| body.tag!(@operation + 'Request') do |request| request.submissionDetails do |details| submission_details(details) end request.resultRecord do |record| record.sourcedGUID do |guid| guid.sourcedId @lis_result_sourcedid end results(record) end end end end end
# File lib/ajims/lti/outcome_request.rb, line 194 def has_required_attributes? @consumer_key && @consumer_secret && @lis_outcome_service_url && @lis_result_sourcedid && @operation end
# File lib/ajims/lti/outcome_request.rb, line 173 def has_result_data? !!@score end
# File lib/ajims/lti/outcome_request.rb, line 163 def has_result_time? !@submitted_at.nil? end
# File lib/ajims/lti/outcome_request.rb, line 185 def result_values(node) if @score node.resultScore do |res_score| res_score.language "en" # 'en' represents the format of the number res_score.textString @score.to_s end end end
# File lib/ajims/lti/outcome_request.rb, line 177 def results(node) return unless has_result_data? node.result do |res| result_values(res) end end
# File lib/ajims/lti/outcome_request.rb, line 167 def submission_details(node) return unless has_result_time? node.submittedAt @submitted_at.to_s end