excel_loader.rb 3.65 KB
Newer Older
1 2 3
# This file is no longer being used.
# Data is now being parsed from Patriot Web.

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
require 'rubyXL'

# Provides utilities for loading schedules from GMU's excel files.
class ExcelLoader
  def initialize(file_path)
    workbook = RubyXL::Parser.parse(file_path)
    @rows = workbook[0]
    @rows = @rows.drop(16) # the first 16 rows are junk data, so remove them
    @semester = Semester.create! season: 'Fall', year: '2018'
    @current_course = nil
  end

  # Loads all data from the Excel file into the database.
  def load_data
    @rows.each do |row|
      if (course = configure_course?(row)) # If this row contained a course, save it
        course.save!
        @current_course = course
      end
      configure_section?(row)&.save! # If this row contained a section, save it
    end
25 26

    load_closures
27 28 29
  end

  private
Zac Wood's avatar
Zac Wood committed
30

31 32 33 34 35 36 37 38
  # create closures for the days there will be no classes
  # see: https://registrar.gmu.edu/calendars/fall-2018/
  def load_closures
    Closure.create! date: Date.new(2018, 9, 3), semester: @semester
    Closure.create! date: Date.new(2018, 10, 8), semester: @semester
    (21..25).each { |n| Closure.create! date: Date.new(2018, 11, n), semester: @semester }
    (10..19).each { |n| Closure.create! date: Date.new(2018, 12, n), semester: @semester }
  end
Zac Wood's avatar
Zac Wood committed
39

40 41
  # Prints the failure, deletes all data added during loading, and raises the failure error.
  def fail(error)
42 43
    logger.fatal error.message
    logger.fatal error.backtrace
44 45 46
    raise error
  end

47
  # Tries to create a course from a given row.
48
  def configure_course?(row)
49
    course_name = row.cells[1]&.value
50 51 52
    course = nil

    # Ensure the course name is valid
53
    if course_name.present? && course_name != 'Total'
54 55 56 57 58 59 60 61 62 63
      # Split the name into its two components, i.e. "CS 112" => ["CS", "112"]
      name_components = course_name.split(' ')

      # Try to save the new course
      course = Course.new
      course.subject = name_components[0]
      course.course_number = name_components[1]
      course.semester = @semester
    end

64
    course
65 66
  end

67
  # Tries to create a section from a given row.
68
  def configure_section?(row)
69
    section_name = row.cells[2]&.value
Zac Wood's avatar
Zac Wood committed
70

71
    # If there is no valid section name, just continue to the next row
Zac Wood's avatar
Zac Wood committed
72 73 74 75 76 77 78 79 80
    return nil if section_name.blank? || section_name == 'Total'

    # The time field in the spreadsheet uses the format "start_time - end_time" i.e. "12:00 PM - 1:15 PM".
    # So, split the times string by the - character
    times = row.cells[23]&.value
    time_strs = times.split('-')

    instructor_val = row.cells[16]
    instructor = if instructor_val.nil? || instructor_val.value == "'-"
81 82
                   "TBA"
                 else
Zac Wood's avatar
Zac Wood committed
83
                   instructor_val.value
84
                 end
Zac Wood's avatar
Zac Wood committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

    location_cell = row.cells[25]
    location = if location_cell.nil? || location_cell.value.include?("'-")
                 "TBA"
               else
                 location_cell.value
               end

    section = CourseSection.create name: section_name,
                                   course: @current_course,
                                   crn: row.cells[6]&.value,
                                   section_type: row.cells[8]&.value,
                                   title: row.cells[11]&.value,
                                   instructor: instructor,
                                   start_date: row.cells[18]&.value,
                                   end_date: row.cells[21]&.value,
                                   days: row.cells[22]&.value,
                                   start_time: time_strs[0].strip,
                                   end_time: time_strs[1].strip,
                                   location: location

    section
107 108
  end
end