concord-consortium/rigse

View on GitHub
rails/app/models/api/v1/offering.rb

Summary

Maintainability
B
6 hrs
Test Coverage
class API::V1::Offering
  include Rails.application.routes.url_helpers
  include Virtus.model
  include RunnablesHelper

  # Optimize SQL queries based on API::V1::Offering structure.
  INCLUDES_DEF = {
      learners: [:report_learner, {student: :user}],
      clazz: {students: :user}
      # TODO when we only support external activity runnables then the following
      # line can be used to optimize the database requests
      # runnable: [:template, :external_report]
  }

  class OfferingStudent
    include Rails.application.routes.url_helpers
    include Virtus.model

    attribute :name, String
    attribute :first_name, String
    attribute :last_name, String
    attribute :username, String
    attribute :user_id, Integer
    attribute :started_activity, Boolean
    attribute :endpoint_url, String
    attribute :learner_report_url, String
    attribute :last_run, Date
    attribute :total_progress, Float
    attribute :detailed_progress, Array

    def initialize(student, offering, protocol, host_with_port, anonymize = false)
      self.name = anonymize ? "#{student.anonymized_first_name} #{student.anonymized_last_name}" : student.user.name
      self.first_name = anonymize ? student.anonymized_first_name : student.user.first_name
      self.last_name = anonymize ? student.anonymized_last_name : student.user.last_name
      self.username = student.user.login
      self.user_id = student.user.id
      learner = offering.learners.find { |l| l.student_id === student.id }
      # Learner object is available only if student has started the activity.
      self.started_activity = learner ? true : false
      self.endpoint_url = learner ? learner.remote_endpoint_url : nil
      self.total_progress = learner ? learner.report_learner.complete_percent : 0
      self.last_run = learner ? learner.report_learner.last_run : nil
      self.learner_report_url = learner && learner.reportable? ? report_portal_learner_url(learner, protocol: protocol, host: host_with_port) : nil
    end
  end

  attribute :id, Integer
  attribute :teacher, String
  attribute :clazz, String
  attribute :clazz_hash, String
  attribute :clazz_id, Integer
  attribute :clazz_info_url, String
  attribute :clazz_is_archived, Boolean
  attribute :activity, String
  attribute :activity_url, String
  attribute :material_type, String
  attribute :report_url, String
  attribute :rubric_url, String
  attribute :rubric_doc_url, String
  attribute :preview_url, String
  attribute :has_teacher_edition, Boolean
  # 2019-07-16 NP:  TODO: deprecate `external_report` in favor of `external_reports`
  attribute :external_report, Hash
  attribute :external_reports, Array
  attribute :reportable, Boolean
  attribute :reportable_activities, Array
  attribute :students, Array[OfferingStudent]

  def report_attributes(report, offering, protocol, host_with_port)
    {
      id: report.id,
      name: report.name,
      url: portal_external_report_url(id: offering.id, report_id: report.id, protocol: protocol, host: host_with_port),
      launch_text: report.launch_text,
      supports_researchers: report.supports_researchers
    }
  end

  def initialize(offering, protocol, host_with_port, current_user, additional_external_report_id, anonymize_students = false)
    runnable = offering.runnable
    self.id = offering.id
    self.teacher = offering.clazz.teacher.name
    self.clazz = offering.clazz.name
    self.clazz_hash = offering.clazz.class_hash
    self.clazz_id = offering.clazz.id
    self.clazz_info_url = offering.clazz.class_info_url(protocol, host_with_port)
    self.clazz_is_archived = offering.clazz.is_archived
    self.activity = offering.name
    self.activity_url = runnable.respond_to?(:url) ? runnable.url : nil
    self.material_type = runnable.material_type
    self.has_teacher_edition = runnable.has_teacher_edition
    self.reportable = offering.reportable?
    self.rubric_url = runnable.respond_to?(:rubric_url) ? runnable.rubric_url : nil
    self.rubric_doc_url = runnable.respond_to?(:rubric_doc_url) ? runnable.rubric_doc_url : nil
    self.report_url = offering.reportable? ? report_portal_offering_url(id: offering.id, protocol: protocol, host: host_with_port) : nil
    self.preview_url = run_url_for(runnable, preview_params(current_user, {protocol: protocol, host: host_with_port}))
    # 2019-07-16 NP:  TODO: deprecate `external_report` in favor of `external_reports`
    if runnable.respond_to?(:external_report) && runnable.external_report
      self.external_report = report_attributes(runnable.external_report, offering, protocol, host_with_port)
    end
    self.external_reports = []
    if runnable.respond_to?(:external_reports) && runnable.external_reports
      runnable.external_reports.each do |report|
        self.external_reports << report_attributes(report, offering, protocol, host_with_port)
      end
    end
    if additional_external_report_id
      additional_report = ExternalReport.find_by_id(additional_external_report_id)
      if additional_report
        self.external_reports << report_attributes(additional_report, offering, protocol, host_with_port)
      end
    end

    self.students = offering.clazz.students.map { |s| OfferingStudent.new(s, offering, protocol, host_with_port, anonymize_students) }
  end
end