class Naseweis::Nase

A class to read a Weisfile and gather user input

@attr_reader [String] filename The path to the file which is used by this

{Nase}

@attr_reader [Array] questions All questions handled by this {Nase}.

To update the questions, use the {#read} method.

@attr_reader [Converter] converter The converter that is used to convert

types

Attributes

converter[R]
filename[R]
questions[R]

Public Class Methods

new(path) click to toggle source

Create a new {Nase} which reads questions from the given file

@param path [String] path to the file with the questions

# File lib/naseweis.rb, line 38
def initialize(path)
  @filename = path
  @questions = {}
  @converter = Converter.new
end

Public Instance Methods

interrogate(instream: $stdin, outstream: $stdout) click to toggle source

Start the question session and return the user answers

@param instream [File] input stream, i.e. stream where data is read from @param outstream [File] output stream, i.e. stream where prompts are

printed to

@return [Hash] Hash of the user answers, where the keys are defined by

the question file.
# File lib/naseweis.rb, line 80
def interrogate(instream: $stdin, outstream: $stdout)
  @io = HighLine.new instream, outstream
  ask @questions
  @io = nil
end
read() click to toggle source

Update the questions and re-read them from the file that the Nase was initialized with

@return [void] @raise [WeisheitError] if the input file is malformed

# File lib/naseweis.rb, line 49
def read
  questions = YAML.load_file(@filename)
  verify questions
  @questions = questions
end
verify(q) click to toggle source

Check whether the given question is wellformed

@param q [Hash,Array] the question or list of questions to check @return [void] @raise [WeisheitError] if the question is malformed

# File lib/naseweis.rb, line 60
def verify(q)
  # Currently only checks if the question type is valid
  if q.is_a? Array
    q.each { |x| verify x }
    return
  end
  type = q['type']
  qs = q['q']
  well = type.nil? || @converter.supported_types.include?(type.intern)
  raise WeisheitError, "invalid type #{type}" unless well
  verify qs if qs.is_a? Array
end

Private Instance Methods

ask(questions) click to toggle source

Ask the given list of questions and return the answers as a Hash

@param questions [Array] list of questions to ask @return [Hash] Hash of the user answers

# File lib/naseweis.rb, line 92
def ask(questions)
  namespace = {}
  questions.each do |q|
    answer = do_question q
    namespace[q['target']] = answer if q.key?('target') && !answer.nil?
  end
  namespace
end
do_question(q) click to toggle source

Handle a single question and return the answer

@param q [Hash] the question data @return [String] for a simple question @return [Array] for a repeating question

# File lib/naseweis.rb, line 106
def do_question(q)
  if q.key? 'desc'
    # Always output the description first
    @io.say q['desc']
  end

  repeat = q['repeat']
  return get_valid_input q if repeat.nil?
  return (1..repeat).collect { get_valid_input q } if repeat.is_a? Integer
  if repeat.is_a? String
    result = [get_valid_input(q)]
    result.push(get_valid_input(q)) while @io.agree repeat
  else
    result = []
    loop do
      line = get_valid_input q
      break if line.empty?
      result << line
    end
  end
  result
end
get_valid_input(q) click to toggle source

Get a single line of user input that is valid for the given question

@param q [Hash] the question which to get input for @return [String] if the question is a simple question @return [Hash] if the question has sub-questions @return [Object] if the question is type-converted

# File lib/naseweis.rb, line 135
def get_valid_input(q)
  prompt = q['q']
  prompt = '' if prompt.nil?
  result = nil
  loop do
    if prompt.is_a? Array
      result = ask prompt
    elsif !q['choices'].nil?
      @io.say prompt
      result = @io.choose(*q['choices'])
    else
      result = @io.ask prompt
    end
    break if q['type'].nil?
    begin
      result = @converter.convert result, q['type']
    rescue ConversionError
      @io.say "invalid value for type #{q['type']}"
    else
      break
    end
  end
  result
end