Class: IMS::LTI::OutcomeResponse

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

Overview

Class for consuming/generating LTI Outcome Responses

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

Error code documentation: www.imsglobal.org/gws/gwsv1p0/imsgws_baseProfv1p0.html#1639667

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 parse the result of an OutcomeRequest to the Tool Consumer. A Tool Consumer will use it generate proper response XML to send back to a Tool Provider

Tool Provider Usage

An OutcomeResponse will generally be created when POSTing an OutcomeRequest through a configured ToolProvider. See the ToolProvider documentation for typical usage.

Tool Consumer Usage

When an outcome request is sent from a Tool Provider 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 a new response and set the appropriate values
res = IMS::LTI::OutcomeResponse.new
res.message_ref_identifier = outcome_request.message_identifier
res.operation = outcome_request.operation
res.code_major = 'success'
res.severity = 'status'

# set a description (optional) and other information based on the type of response
if outcome_request.replace_request?
  res.description = "Your old score of 0 has been replaced with #{outcome_request.score}"
elsif outcome_request.read_request?
  res.description = "You score is 50"
  res.score = 50
elsif outcome_request.delete_request?
  res.description = "You score has been cleared"
else
  res.code_major = 'unsupported'
  res.severity = 'status'
  res.description = "#{outcome_request.operation} is not supported"
end

# the generated xml is returned to the Tool Provider
res.generate_response_xml

Constant Summary collapse

CODE_MAJOR_CODES =
%w{success processing failure unsupported}
SEVERITY_CODES =
%w{status warning error}

Instance Attribute Summary collapse

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

Constructor Details

#initialize(opts = {}) ⇒ OutcomeResponse

Create a new OutcomeResponse

Parameters:

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

    initialization hash



60
61
62
63
64
# File 'lib/ims/lti/outcome_response.rb', line 60

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

Instance Attribute Details

#code_majorObject

Returns the value of attribute code_major.



50
51
52
# File 'lib/ims/lti/outcome_response.rb', line 50

def code_major
  @code_major
end

#descriptionObject

Returns the value of attribute description.



50
51
52
# File 'lib/ims/lti/outcome_response.rb', line 50

def description
  @description
end

#message_identifierObject

Returns the value of attribute message_identifier.



50
51
52
# File 'lib/ims/lti/outcome_response.rb', line 50

def message_identifier
  @message_identifier
end

#message_ref_identifierObject

Returns the value of attribute message_ref_identifier.



50
51
52
# File 'lib/ims/lti/outcome_response.rb', line 50

def message_ref_identifier
  @message_ref_identifier
end

#operationObject

Returns the value of attribute operation.



50
51
52
# File 'lib/ims/lti/outcome_response.rb', line 50

def operation
  @operation
end

#post_responseObject

Returns the value of attribute post_response.



50
51
52
# File 'lib/ims/lti/outcome_response.rb', line 50

def post_response
  @post_response
end

#request_typeObject

Returns the value of attribute request_type.



50
51
52
# File 'lib/ims/lti/outcome_response.rb', line 50

def request_type
  @request_type
end

#response_codeObject

Returns the value of attribute response_code.



50
51
52
# File 'lib/ims/lti/outcome_response.rb', line 50

def response_code
  @response_code
end

#scoreObject

Returns the value of attribute score.



50
51
52
# File 'lib/ims/lti/outcome_response.rb', line 50

def score
  @score
end

#severityObject

Returns the value of attribute severity.



50
51
52
# File 'lib/ims/lti/outcome_response.rb', line 50

def severity
  @severity
end

Class Method Details

.from_post_response(post_response) ⇒ Object

Convenience method for creating a new OutcomeResponse from a response object

req = IMS::LTI::OutcomeResponse.from_post_response(response)


69
70
71
72
# File 'lib/ims/lti/outcome_response.rb', line 69

def self.from_post_response(post_response)
  response = OutcomeResponse.new
  response.process_post_response(post_response)
end

Instance Method Details

#failure?Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/ims/lti/outcome_response.rb', line 90

def failure?
  @code_major == 'failure'
end

#generate_response_xmlString

Generate XML based on the current configuration

Returns:

  • (String)

    The response xml



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/ims/lti/outcome_response.rb', line 134

def generate_response_xml
  builder = Builder::XmlMarkup.new
  builder.instruct!

  builder.imsx_POXEnvelopeResponse("xmlns" => "http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0") do |env|
    env.imsx_POXHeader do |header|
      header.imsx_POXResponseHeaderInfo do |info|
        info.imsx_version "V1.0"
        info.imsx_messageIdentifier @message_identifier || IMS::LTI::generate_identifier
        info.imsx_statusInfo do |status|
          status.imsx_codeMajor @code_major
          status.imsx_severity @severity
          status.imsx_description @description
          status.imsx_messageRefIdentifier @message_ref_identifier
          status.imsx_operationRefIdentifier @operation
        end
      end
    end #/header
    env.imsx_POXBody do |body|
      unless unsupported?
        if @operation == OutcomeRequest::READ_REQUEST
          body.tag!(@operation + 'Response') do |request|
            request.result do |res|
              res.resultScore do |res_score|
                res_score.language "en" # 'en' represents the format of the number
                res_score.textString @score.to_s
              end
            end #/result
          end
        else
          body.tag!(@operation + 'Response')
        end #/operationResponse
      end
    end #/body
  end
end

#has_error?Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/ims/lti/outcome_response.rb', line 102

def has_error?
  @severity == 'error'
end

#has_warning?Boolean

Returns:

  • (Boolean)


98
99
100
# File 'lib/ims/lti/outcome_response.rb', line 98

def has_warning?
  @severity == 'warning'
end

#process_post_response(post_response) ⇒ Object



74
75
76
77
78
79
80
# File 'lib/ims/lti/outcome_response.rb', line 74

def process_post_response(post_response)
  self.post_response = post_response
  self.response_code = post_response.code
  xml = post_response.body
  self.process_xml(xml)
  self
end

#process_xml(xml) ⇒ Object

Parse Outcome Response data from XML



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/ims/lti/outcome_response.rb', line 107

def process_xml(xml)
  if xml.include?('#<UUID:0x')              # Blackboard bug!
    m_id = xml.match('#<UUID:(\w+)>')[1].hex.to_i
    xml = xml.sub(/#<UUID:\w+>/, m_id.to_s)
  end
  begin
    doc = REXML::Document.new xml
  rescue => e
    raise IMS::LTI::XMLParseError, "#{e}\nOriginal xml: '#{xml}'"
  end
  @message_identifier = doc.text('//imsx_statusInfo/imsx_messageIdentifier')
  @message_identifier = doc.text('//imsx_messageIdentifier') if @message_identifier.nil?
  @message_identifier = @message_identifier.nil? ? '0' : @message_identifier.to_s
  @code_major = doc.text("//imsx_statusInfo/imsx_codeMajor")
  @code_major.downcase! if @code_major
  @severity = doc.text("//imsx_statusInfo/imsx_severity")
  @severity.downcase! if @severity
  @description = doc.text("//imsx_statusInfo/imsx_description")
  @description = @description.to_s if @description
  @message_ref_identifier = doc.text("//imsx_statusInfo/imsx_messageRefIdentifier")
  @operation = doc.text("//imsx_statusInfo/imsx_operationRefIdentifier")
  @score = doc.text("//readResultResponse//resultScore/textString")
  @score = @score.to_s if @score
end

#processing?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/ims/lti/outcome_response.rb', line 86

def processing?
  @code_major == 'processing'
end

#success?Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/ims/lti/outcome_response.rb', line 82

def success?
  @code_major == 'success'
end

#unsupported?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/ims/lti/outcome_response.rb', line 94

def unsupported?
  @code_major == 'unsupported'
end