class GithubToCanvasQuiz::Synchronizer::Quiz

Synchronize a quiz to Canvas based on the contents of a given directory Given a directory with valid markdown files:

phase-1-quiz-arrays | questions | |– 00.md | |– 01.md |– README.md

Useage:

client = CanvasAPI::Client.new(host: host, api_key: api_key)
Synchronizer::Quiz.new(client, 'phase-1-quiz-arrays')

Attributes

client[R]
path[R]
questions_with_path[R]
quiz[R]
repo[R]

Public Class Methods

new(client, path) click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 22
def initialize(client, path)
  path = File.expand_path(path)
  raise DirectoryNotFoundError unless Pathname(path).directory?

  @client = client
  @path = path
  @repo = RepositoryInterface.new(path)
  @quiz = parse_quiz
  @questions_with_path = parse_questions_with_path
end

Public Instance Methods

sync() click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 33
def sync
  backup_canvas_to_json!
  sync_quiz!
  sync_questions!
  backup_canvas_to_json!
end

Private Instance Methods

backup_canvas_to_json!() click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 139
def backup_canvas_to_json!
  quiz_data = client.get_single_quiz(quiz.course_id, quiz.id)
  questions_data = client.list_questions(quiz.course_id, quiz.id)

  json_data = JSON.pretty_generate({ quiz: quiz_data, questions: questions_data })
  File.write(json_path, json_data)
  repo.commit_files(json_path, 'Created Canvas snapshot')
end
create_question_and_update_frontmatter!(question, path) click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 118
def create_question_and_update_frontmatter!(question, path)
  canvas_question = client.create_question(question.course_id, question.quiz_id, { 'question' => question.to_h })
  question.id = canvas_question['id']
  update_frontmatter(path, question)
end
create_quiz_and_update_frontmatter!() click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 95
def create_quiz_and_update_frontmatter!
  canvas_quiz = client.create_quiz(quiz.course_id, { 'quiz' => quiz.to_h })
  quiz.id = canvas_quiz['id']
  update_frontmatter(quiz_path, quiz)
end
get_answer_ids!(question, canvas_question) click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 68
def get_answer_ids!(question, canvas_question)
  question.answers.each do |answer|
    # match the markdown answer to the Canvas answer based on the answer text
    canvas_answer = canvas_question['answers'].find do |canvas_answer|
      if canvas_answer['html'].nil? || canvas_answer['html'].empty?
        canvas_answer['text'] == answer.text
      else
        canvas_answer['html'] == answer.text
      end
    end
    answer.id = canvas_answer['id'].to_i if canvas_answer
  end
end
json_path() click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 148
def json_path
  File.join(path, '.canvas-snapshot.json')
end
parse_questions_with_path() click to toggle source

Get question data from Markdown files and return a Model::Question along with its path

# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 50
def parse_questions_with_path
  # read Canvas question data
  canvas_questions = client.list_questions(quiz.course_id, quiz.id)
  
  # read Markdown data
  Dir["#{path}/questions/*.md"].map do |question_path|
    question = Parser::Markdown::Question.new(File.read(question_path)).parse
    question.quiz_id = quiz.id
    question.course_id = quiz.course_id
    
    # find the matching Canvas answer
    canvas_question = canvas_questions.find { |canvas_question| canvas_question['id'] == question.id }
    get_answer_ids!(question, canvas_question) if canvas_question

    [question, question_path] # need that question path... gotta be a better way!
  end
end
parse_quiz() click to toggle source

Get quiz data from the Markdown file and return a Model::Quiz

# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 43
def parse_quiz
  raise GithubToCanvasQuiz::FileNotFoundError unless Pathname(quiz_path).exist?

  Parser::Markdown::Quiz.new(quiz_path).parse
end
quiz_path() click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 101
def quiz_path
  File.join(path, 'README.md')
end
remove_deleted_questions!() click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 128
def remove_deleted_questions!
  ids = questions_with_path.map { |question_with_path| question_with_path.first.id }
  client.list_questions(quiz.course_id, quiz.id).each do |canvas_question|
    id = canvas_question['id']
    unless ids.include?(id)
      # delete questions that are no longer present in the repo
      client.delete_question(quiz.course_id, quiz.id, id)
    end
  end
end
sync_questions!() click to toggle source

Create or update questions on Canvas

# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 106
def sync_questions!
  questions_with_path.each do |question_with_path|
    question, path = question_with_path
    if question.id
      update_question!(question)
    else
      create_question_and_update_frontmatter!(question, path)
    end
  end
  remove_deleted_questions!
end
sync_quiz!() click to toggle source

create or update quiz on Canvas

# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 83
def sync_quiz!
  if quiz.id
    update_quiz!
  else
    create_quiz_and_update_frontmatter!
  end
end
update_frontmatter(filepath, markdownable) click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 152
def update_frontmatter(filepath, markdownable)
  parsed = FrontMatterParser::Parser.parse_file(filepath)
  new_markdown = MarkdownBuilder.build do |md|
    md.frontmatter(markdownable.frontmatter_hash)
    md.md(parsed.content)
  end
  File.write(filepath, new_markdown)
  repo.commit_files(filepath, 'Updated frontmatter')
end
update_question!(question) click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 124
def update_question!(question)
  client.update_question(question.course_id, question.quiz_id, question.id, { 'question' => question.to_h })
end
update_quiz!() click to toggle source
# File lib/github_to_canvas_quiz/synchronizer/quiz.rb, line 91
def update_quiz!
  client.update_quiz(quiz.course_id, quiz.id, { 'quiz' => quiz.to_h })
end