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
Zac Wood's avatar
Zac Wood committed
25
26

    load_closures
27
28
29
  end

  private
Zac Wood's avatar
Zac Wood committed
30

Zac Wood's avatar
Zac Wood committed
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 == "'-"
Zac Wood's avatar
Zac Wood committed
81
82
                   "TBA"
                 else
Zac Wood's avatar
Zac Wood committed
83
                   instructor_val.value
Zac Wood's avatar
Zac Wood committed
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