class Spirit::Render::Problem

Renders a single problem. This class doesn't do anything useful; use the child classes (e.g. {Spirit::Render::Multi}) instead. Child classes should override {#valid?}.

Constants

ANSWER

Required key in YAML markup. Value contains answers.

FORMAT

Required key in YAML markup. Value indicates type of problem.

ID

Generated ID.

KEYS

Required keys.

QUESTION

Required key in YAML markup. Value contains question body.

Attributes

digest[R]
id[RW]
nesting[RW]

Public Class Methods

accessor(*args) click to toggle source

Dynamically creates accessor methods for YAML values. @example

accessor :id
# File lib/spirit/render/templates/problem.rb, line 50
def accessor(*args)
  args.each { |arg| define_method(arg) { @yaml[arg] } }
end
get_instance(hash, digest) click to toggle source

@return [Problem] problem

# File lib/spirit/render/templates/problem.rb, line 55
def get_instance(hash, digest)
  raise RenderError, "Missing 'format' key in given YAML" unless instantiable? hash
  klass = Spirit::Render.const_get(hash[FORMAT].capitalize)
  raise NameError unless klass < Problem
  klass.new(hash, digest)
rescue NameError
  raise RenderError, 'Unrecognized format: %p' % hash[FORMAT]
end
new(yaml, digest) click to toggle source

Creates a new problem from the given YAML. @param [Hash] yaml parsed yaml object @param [String] digest SHA-256 hash of yaml text @param [Fixnum] id integer ID of question

# File lib/spirit/render/templates/problem.rb, line 80
def initialize(yaml, digest)
  @yaml, @digest, @nesting, @id = yaml, digest, [], 0
  raise RenderError.new('Invalid problem.') unless @yaml[QUESTION].is_a? String
  @yaml[QUESTION] = markdown.render @yaml[QUESTION]
end
parse(text) click to toggle source

Parses the given text for questions and answers. If the given text does not contain valid YAML or does not contain the format key, raises an {Spirit::Render::RenderError}. @param [String] text embedded yaml @return [Problem] problem

# File lib/spirit/render/templates/problem.rb, line 39
def parse(text)
  digest = OpenSSL::Digest::SHA256.digest text
  yaml   = YAML.load text
  get_instance(yaml, digest)
rescue ::Psych::SyntaxError => e
  raise RenderError, e.message
end

Private Class Methods

instantiable?(hash) click to toggle source
# File lib/spirit/render/templates/problem.rb, line 66
def instantiable?(hash)
  hash.is_a?(Hash) and hash.has_key?(FORMAT)
end

Public Instance Methods

answer() click to toggle source

Retrieves the answer from the given YAML object in a serializable form. @see serializable @return [String, Numeric, TrueClass, FalseClass] answer

# File lib/spirit/render/templates/problem.rb, line 96
def answer
  serialize @yaml[ANSWER]
end
render(locals={}) click to toggle source

@todo TODO should probably show some error message in the preview,

so that the author doesn't have to read the logs.
Calls superclass method
# File lib/spirit/render/templates/problem.rb, line 88
def render(locals={})
  raise RenderError.new('Invalid problem.') unless valid?
  super @yaml.merge(locals)
end

Private Instance Methods

serialize(obj) click to toggle source

If obj is one of String, Numeric, true, or false, the it's returned. Otherwise, to_s is invoked on the object and returned. @return [String, Numeric, TrueClass, FalseClass] answer

# File lib/spirit/render/templates/problem.rb, line 105
def serialize(obj)
  case obj
  when String, Numeric, TrueClass, FalseClass then obj
  else obj.to_s end
end
valid?() click to toggle source

Checks that all required {KEYS} exist in the YAML, and that the question is given as a string. @return [Boolean] true iff the parsed yaml contains a valid problem.

# File lib/spirit/render/templates/problem.rb, line 114
def valid?
  KEYS.all? { |key| @yaml.has_key? key } and question.is_a? String
end