diff --git a/schedules/.gitignore b/schedules/.gitignore index b5a9845bb1470020efc0656e18054892284371b8..e81eba5ef246b6382d4d6cc35834a6b64efa119f 100644 --- a/schedules/.gitignore +++ b/schedules/.gitignore @@ -26,3 +26,6 @@ /node_modules yarn-debug.log* .yarn-integrity + +coverage +subjects diff --git a/schedules/app/controllers/api/course_sections_controller.rb b/schedules/app/controllers/api/course_sections_controller.rb index 105589038e9735a54e4103cfb6aa2ea2dd75c2f1..5318093d7a601650f999e4cbcf9b3180b75d7826 100644 --- a/schedules/app/controllers/api/course_sections_controller.rb +++ b/schedules/app/controllers/api/course_sections_controller.rb @@ -11,9 +11,10 @@ class API::CourseSectionsController < ApplicationController param :instructor, String, desc: "Get course sections being taught by this instructor" def index @sections = CourseSection - .select('course_sections.*, courses.semester_id, instructors.name AS instructor_name') - .joins(:course).where('courses.semester_id = ?', @semester.id) - .joins(:instructor) + .where(semester: @semester) + .joins(:course) + .joins(:instructor) + .select('course_sections.*, instructors.name AS instructor_name') if params.key?(:course_id) @sections = @sections.where(course_id: params[:course_id]) diff --git a/schedules/app/controllers/api/courses_controller.rb b/schedules/app/controllers/api/courses_controller.rb index 3408e3bcfddfe82010badbf1248dbb4676a7349a..8fda1aa6fbe0598c2b14ff45ae9a0b074254ceca 100644 --- a/schedules/app/controllers/api/courses_controller.rb +++ b/schedules/app/controllers/api/courses_controller.rb @@ -8,7 +8,7 @@ class API::CoursesController < ApplicationController param :subject, String, desc: 'Course subject, e.g. "CS" or "ACCT"' param :course_number, Integer, desc: 'Course number, e.g. "112"' def index - @courses = Course.where(semester_id: params[:semester_id]) + @courses = Course.all if params.key?(:subject) @courses = @courses.where("UPPER(courses.subject) LIKE ?", "%#{params[:subject]}%") @@ -21,7 +21,6 @@ class API::CoursesController < ApplicationController result = @courses.map do |c| { id: c.id, - semester_id: c.semester_id, subject: c.subject, course_number: c.course_number, description: c.description, diff --git a/schedules/app/controllers/courses_controller.rb b/schedules/app/controllers/courses_controller.rb index 988aaf7e20d99fb32c192e350087ba5d6cd292e1..53dfa4f740112fd03e4daa40a051f43bc57d788c 100644 --- a/schedules/app/controllers/courses_controller.rb +++ b/schedules/app/controllers/courses_controller.rb @@ -2,18 +2,6 @@ class CoursesController < ApplicationController def show # Load the course with the id passed in the URL. @course = Course.find_by_id(params[:id]) - - # If the user changes the semester while looking at a course, - # we need to display the page for the course with the same subject and course number - # in that semester. - unless @course.semester == @semester - # find the course we should redirect to - @course = Course.find_by(subject: @course.subject, course_number: @course.course_number, semester: @semester) - - # redirect to the url for that course - redirect_to course_url(@course) - end - - @sections = @course.course_sections + @sections = @course.course_sections.where(semester: @semester) end end diff --git a/schedules/app/controllers/instructors_controller.rb b/schedules/app/controllers/instructors_controller.rb index 3a2bd4be460f76010dc1168211e59aaff10efc8e..c7e067815d1fd695b490ce6d0aa8506aa85d62b9 100644 --- a/schedules/app/controllers/instructors_controller.rb +++ b/schedules/app/controllers/instructors_controller.rb @@ -7,7 +7,7 @@ class InstructorsController < ApplicationController @instructor = Instructor.find_by_id(params[:id]) # find the courses being taught this semester - sections = CourseSection.where(instructor: @instructor).joins(course: :semester).where("semesters.id = ?", @semester.id) + sections = CourseSection.where(instructor: @instructor, semester: @semester) @courses = Course.build_set(sections) # build the list of courses the instructor has taught in the past diff --git a/schedules/app/helpers/search_helper.rb b/schedules/app/helpers/search_helper.rb index 486773a9063ae23da762a6620e81fecd3ff260ee..ce0dedf97a557eae7a6693f92287413d8945f7a9 100644 --- a/schedules/app/helpers/search_helper.rb +++ b/schedules/app/helpers/search_helper.rb @@ -27,15 +27,15 @@ module SearchHelper def self.fetchall(search_string, sort_mode: :auto, semester: :fall2018) query_data = GenericQueryData.new(search_string, sort_mode, semester) models = [] - models += fetch_instructors query_data - models += fetch_courses query_data + models += fetch_instructors(query_data) + models += fetch_courses(query_data) build_list(models) end def self.fetch_instructors(query_data) Instructor.from_name(Instructor.select("instructors.*, COUNT(courses.id) AS section_count").from("course_sections"), query_data.search_string) .joins("LEFT OUTER JOIN instructors ON instructors.id = course_sections.instructor_id") - .joins("LEFT OUTER JOIN courses ON courses.id = course_sections.course_id AND courses.semester_id = #{query_data.semester.id}") + .joins("LEFT OUTER JOIN courses ON courses.id = course_sections.course_id AND course_sections.semester_id = #{query_data.semester.id}") .group("instructors.id").all end @@ -46,7 +46,7 @@ module SearchHelper base_query = Course.select("courses.*, count(course_sections.id) AS section_count") .left_outer_joins(:course_sections) .having("count(course_sections.id) > 0") - .where("courses.semester_id = ?", query_data.semester) + .where("course_sections.semester_id = ?", query_data.semester) .group("courses.id") subj = nil diff --git a/schedules/app/models/course.rb b/schedules/app/models/course.rb index bcd3081e9a3fcc494937cc1a9086c22efa65c270..330b42758e04ceb5acfa97082cdc3b69a46d511c 100644 --- a/schedules/app/models/course.rb +++ b/schedules/app/models/course.rb @@ -1,13 +1,10 @@ # Contains logic regarding the +Course+ model. class Course < ApplicationRecord - # Each course belongs to a +Semester+ - belongs_to :semester has_many :course_sections # Ensure all necessary are fields present. validates :course_number, presence: true validates :subject, presence: true - validates :semester_id, presence: true def full_name "#{subject} #{course_number}" diff --git a/schedules/app/models/course_section.rb b/schedules/app/models/course_section.rb index 2f4db5892cabc7f0b3cadb2ace5ac25dd2594ec1..8eb9c1a8dbcce799f050ac593a33ed65735845d6 100644 --- a/schedules/app/models/course_section.rb +++ b/schedules/app/models/course_section.rb @@ -3,12 +3,16 @@ class CourseSection < ApplicationRecord # Each +CourseSection+ belongs to a +Course+ and an +Instructor+. belongs_to :course belongs_to :instructor + + # Each course belongs to a +Semester+ + belongs_to :semester # Ensure all necessary fields are present. validates :name, presence: true validates :crn, presence: true validates :title, presence: true validates :course_id, presence: true + validates :semester_id, presence: true def overlaps?(other) t1_start, t1_end = Time.parse(start_time), Time.parse(end_time) @@ -18,7 +22,7 @@ class CourseSection < ApplicationRecord end def self.latest_by_crn(crn) - where(crn: crn).min_by { |s| s.course.semester.id } + where(crn: crn).min_by { |s| s.semester.id } end # Select all course sections that have an instructor that matches the given name diff --git a/schedules/app/models/schedule.rb b/schedules/app/models/schedule.rb index 6e6d7967428c56dd384245b7aad05f7a312f90ac..49ea5c55536b17afc79e1df07e8499a3b67a8b69 100644 --- a/schedules/app/models/schedule.rb +++ b/schedules/app/models/schedule.rb @@ -95,7 +95,7 @@ class Schedule # @return [Array] def exdates_for_section(section) # Generate exdates for all closures in a semester - exdates = Closure.where(semester: section.course.semester).map { |closure| + exdates = Closure.where(semester: section.semester).map { |closure| generate_exdate(closure.date.to_formatted_s(:number), section.start_time) } diff --git a/schedules/app/views/shared/_course.html.erb b/schedules/app/views/shared/_course.html.erb index 1129e3eb2adb42b5bd25df0a9a2637c9d179ec76..40100afd776cbcbe5bf0bad798df5c23b6751071 100644 --- a/schedules/app/views/shared/_course.html.erb +++ b/schedules/app/views/shared/_course.html.erb @@ -1,5 +1,11 @@ <% expanded = false unless defined? expanded %> +<% if defined?(@instructor) %> + <% sections = course.course_sections.where(instructor: @instructor, semester: @semester).order(:name) %> +<% else %> + <% sections = course.course_sections.where(semester: @semester).order(:name) %> +<% end %> +
@@ -24,7 +30,7 @@
- <%= course.course_sections.count %> sections + <%= sections.count %> sections

<%= course.description %>

@@ -42,11 +48,7 @@
"> - <% if defined?(@instructor) %> - <%= render partial: 'shared/section', collection: course.course_sections.where(instructor: @instructor).order(:name), locals: { course: course } %> - <% else %> - <%= render partial: 'shared/section', collection: course.course_sections.order(:name), locals: { course: course } %> - <% end %> + <%= render partial: 'shared/section', collection: sections, locals: { course: course } %>
diff --git a/schedules/db/migrate/20190210152552_remove_semester_fk_from_course.rb b/schedules/db/migrate/20190210152552_remove_semester_fk_from_course.rb new file mode 100644 index 0000000000000000000000000000000000000000..4489ffeda9a92aac20dd9bec1249d4a74adb68e5 --- /dev/null +++ b/schedules/db/migrate/20190210152552_remove_semester_fk_from_course.rb @@ -0,0 +1,6 @@ +class RemoveSemesterFkFromCourse < ActiveRecord::Migration[5.1] + def change + remove_column :courses, :semester_id + add_reference :course_sections, :semester, foreign_key: true + end +end diff --git a/schedules/db/schema.rb b/schedules/db/schema.rb index 219b2a4637d1f20bef01231e11a456a8bba619e2..c964202de767a33ba585e9003709b0298c1a3492 100644 --- a/schedules/db/schema.rb +++ b/schedules/db/schema.rb @@ -10,14 +10,11 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180927140017) do - - # These are extensions that must be enabled in order to support this database - enable_extension "plpgsql" +ActiveRecord::Schema.define(version: 20190210152552) do create_table "closures", force: :cascade do |t| t.date "date" - t.bigint "semester_id" + t.integer "semester_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["semester_id"], name: "index_closures_on_semester_id" @@ -38,25 +35,25 @@ ActiveRecord::Schema.define(version: 20180927140017) do t.string "campus" t.string "notes" t.integer "size_limit" - t.bigint "course_id" + t.integer "course_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.bigint "instructor_id" + t.integer "instructor_id" + t.integer "semester_id" t.index ["course_id"], name: "index_course_sections_on_course_id" t.index ["instructor_id"], name: "index_course_sections_on_instructor_id" + t.index ["semester_id"], name: "index_course_sections_on_semester_id" end create_table "courses", force: :cascade do |t| t.string "subject" t.string "course_number" - t.bigint "semester_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "description" t.string "credits" t.string "title" t.string "prereqs" - t.index ["semester_id"], name: "index_courses_on_semester_id" end create_table "instructors", force: :cascade do |t| @@ -72,8 +69,4 @@ ActiveRecord::Schema.define(version: 20180927140017) do t.datetime "updated_at", null: false end - add_foreign_key "closures", "semesters" - add_foreign_key "course_sections", "courses" - add_foreign_key "course_sections", "instructors" - add_foreign_key "courses", "semesters" end diff --git a/schedules/db/seeds.rb b/schedules/db/seeds.rb index 20612b8a0ddf157459d5bec43f73cd7b70f4e6d9..57c3b48949180e1f890d49c8a144869be282c591 100644 --- a/schedules/db/seeds.rb +++ b/schedules/db/seeds.rb @@ -22,7 +22,7 @@ def parse_courses(subjects) courses end -def load_courses(courses, semester) +def load_courses(courses) insert_hashes = courses.map do |course| { subject: course[:subject], @@ -31,7 +31,6 @@ def load_courses(courses, semester) credits: course[:credits], description: course[:description], prereqs: course[:prereqs], - semester: semester } end @@ -64,8 +63,7 @@ def load_sections(sections_in, semester) end course = Course.find_or_create_by!(subject: section[:subj], - course_number: section[:course_number], - semester: semester) + course_number: section[:course_number]) instructor = Instructor.find_or_create_by!(name: section[:instructor]) @@ -82,7 +80,8 @@ def load_sections(sections_in, semester) end_time: section[:end_time], location: section[:location], course: course, - instructor: instructor) + instructor: instructor, + semester: semester) end all_sections.each { |s| CourseSection.find_or_create_by! s } @@ -117,24 +116,23 @@ def main [parser.parse_semesters.first] else # expand to include however many semesters you want - parser.parse_semesters[0..6] + parser.parse_semesters[0..2] end - courses = nil + puts "\tParsing subjects..." + subjects = parser.parse_subjects(semesters.first[:value]) + + puts "\tParsing courses from catalog.gmu.edu..." + courses = parse_courses(subjects) if courses.nil? + + puts "\tLoading courses..." + load_courses(courses) + semesters.each do |semester| puts "#{semester[:season]} #{semester[:year]}" db_semester = Semester.find_or_create_by!(season: semester[:season], year: semester[:year]) - puts "\tParsing subjects..." - subjects = parser.parse_subjects(semester[:value]) - - puts "\tParsing courses from catalog.gmu.edu..." - courses = parse_courses(subjects) if courses.nil? - - puts "\tLoading courses..." - load_courses(courses, db_semester) - puts "\tParsing sections from Patriot Web..." sections_in = parse_sections(semester[:value], subjects) diff --git a/schedules/test/controllers/api/course_sections_controller_test.rb b/schedules/test/controllers/api/course_sections_controller_test.rb index d1d99f4ba18876f9706965e6e0805d0cddc5e10e..71f9e3f39e60f9bea06cb1d7b20fe0c99173adc4 100644 --- a/schedules/test/controllers/api/course_sections_controller_test.rb +++ b/schedules/test/controllers/api/course_sections_controller_test.rb @@ -2,14 +2,15 @@ require 'test_helper' class API::CourseSectionsControllerTest < ActionDispatch::IntegrationTest test 'should get index' do - get api_course_sections_url course_id: courses(:cs112).id, semester_id: semesters(:fall2018).id + get api_course_sections_url(course_id: courses(:cs112).id, + semester_id: semesters(:fall2018).id) + assert_response :success sections_returned = JSON.parse @response.body num_sections = CourseSection - .joins(course: :semester) - .where('semesters.id = ?', semesters(:fall2018).id) - .where(course_id: courses(:cs112).id).count + .where(course_id: courses(:cs112).id) + .where(semester: semesters(:fall2018)).count assert_equal num_sections, sections_returned.count end diff --git a/schedules/test/controllers/api/courses_controller_test.rb b/schedules/test/controllers/api/courses_controller_test.rb index c130c3e46a26dfd219900dd44339931a70519484..0dfd9cca1b14b2ee836f56b41e22f9eab41c7c57 100644 --- a/schedules/test/controllers/api/courses_controller_test.rb +++ b/schedules/test/controllers/api/courses_controller_test.rb @@ -2,30 +2,30 @@ require 'test_helper' class API::CoursesControllerTest < ActionDispatch::IntegrationTest test '#index should return all courses' do - get api_courses_url semester_id: semesters(:fall2018).id + get api_courses_url assert_response :success courses_returned = JSON.parse @response.body - courses_count = Course.where(semester_id: semesters(:fall2018).id).count + courses_count = Course.all.count assert_equal courses_count, courses_returned.count end test '#index should return filtered by subject case insensitive' do - get api_courses_url subject: "Cs", semester_id: semesters(:fall2018).id + get api_courses_url(subject: "Cs") assert_response :success courses_returned = JSON.parse @response.body - courses_count = Course.where(subject: "CS", semester_id: semesters(:fall2018).id).count + courses_count = Course.where(subject: "CS").count assert_equal courses_count, courses_returned.count end test '#index should return filtered by subject and course number' do - get api_courses_url subject: "CS", course_number: "112", semester_id: semesters(:fall2018).id + get api_courses_url(subject: "CS", course_number: "112") assert_response :success courses_returned = JSON.parse @response.body - courses_count = Course.where(subject: "CS", course_number: "112", semester_id: semesters(:fall2018).id).count + courses_count = Course.where(subject: "CS", course_number: "112").count assert_equal courses_count, courses_returned.count end @@ -33,7 +33,7 @@ class API::CoursesControllerTest < ActionDispatch::IntegrationTest test '#show should return course_sections for course' do cs_112_id = courses(:cs112).id - get api_course_url id: cs_112_id, semester_id: semesters(:fall2018).id + get api_course_url(id: cs_112_id) assert_response :success sections_returned = JSON.parse @response.body diff --git a/schedules/test/controllers/courses_controller_test.rb b/schedules/test/controllers/courses_controller_test.rb index e3fdb5a9cdfb9470ef2049fd56330b8bfd4573ac..489d03d592f6affbf8f4e5057f62797ec71e313f 100644 --- a/schedules/test/controllers/courses_controller_test.rb +++ b/schedules/test/controllers/courses_controller_test.rb @@ -7,6 +7,6 @@ class CoursesControllerTest < ActionDispatch::IntegrationTest assert_response :success # assert every course section is displayed - assert_select '.section-item', c.course_sections.count + assert_select '.section-item', c.course_sections.where(semester: semesters(:fall2018)).count end end diff --git a/schedules/test/fixtures/course_sections.yml b/schedules/test/fixtures/course_sections.yml index a10970038461917b2f1bf2b36ad53d2913b09fed..167223d3f5009547bedeeec5c4370df7cbf28b8e 100644 --- a/schedules/test/fixtures/course_sections.yml +++ b/schedules/test/fixtures/course_sections.yml @@ -12,6 +12,7 @@ cs112001: location: Innovation Hall 204 course: cs112 instructor: kinga + semester: fall2018 cs112002: name: CS 112 002 @@ -25,6 +26,7 @@ cs112002: end_time: 2:00 pm course: cs112 instructor: luke + semester: fall2018 cs211001: name: CS 211 001 @@ -36,8 +38,9 @@ cs211001: start_time: 2:30 pm end_time: 3:00 pm location: ENGR 200 - course: cs211spring + course: cs211 instructor: otten + semester: spring2018 cs112001spring: name: CS 112 001 @@ -49,8 +52,9 @@ cs112001spring: start_time: 12:00 pm end_time: 1:00 pm location: Innovation Hall 204 - course: cs112spring + course: cs112 instructor: kinga + semester: spring2018 acct110001: name: ACCT 110 001 @@ -62,5 +66,6 @@ acct110001: start_time: 12:00 pm end_time: 1:00 pm location: Innovation Hall 204 - course: acct110spring + course: acct110 instructor: business_man + semester: spring2018 diff --git a/schedules/test/fixtures/courses.yml b/schedules/test/fixtures/courses.yml index 2d1f1821f29990dcc752e3884de18c87ec60a065..1695827dc40887b97793dd4a50c11ba762371f5f 100644 --- a/schedules/test/fixtures/courses.yml +++ b/schedules/test/fixtures/courses.yml @@ -3,24 +3,13 @@ cs112: subject: CS course_number: 112 - semester: fall2018 cs211: subject: CS course_number: 211 - semester: fall2018 -acct110spring: +acct110: subject: ACCT course_number: 110 - semester: spring2018 -cs110spring: - subject: CS - course_number: 110 - semester: spring2018 - -cs112spring: - subject: CS - course_number: 112 - semester: spring2018 + diff --git a/schedules/test/models/course_section_test.rb b/schedules/test/models/course_section_test.rb index 1fb17e085a547099eb879524d49eea4a2febbecf..970600232ab7b607555ae38a03e08e19f24fab03 100644 --- a/schedules/test/models/course_section_test.rb +++ b/schedules/test/models/course_section_test.rb @@ -13,8 +13,9 @@ class CourseSectionTest < ActiveSupport::TestCase CourseSection.create! name: 'Test section', crn: '12345', title: 'Test title', - course_id: courses(:cs211).id, - instructor_id: instructors(:luke).id + course: courses(:cs211), + instructor: instructors(:luke), + semester: semesters(:fall2018) end test '#with_instructor filters correctly' do @@ -24,6 +25,6 @@ class CourseSectionTest < ActiveSupport::TestCase test '#latest_by_crn sorts correctly' do s = CourseSection.latest_by_crn(70192) - assert_equal semesters(:fall2018).id, s.course.semester.id + assert_equal semesters(:fall2018).id, s.semester.id end end diff --git a/schedules/test/models/course_test.rb b/schedules/test/models/course_test.rb index a9819248b9296555dff75b7c31133899615d0346..d0f979a89a853872ba858c2444fa23e622002d23 100644 --- a/schedules/test/models/course_test.rb +++ b/schedules/test/models/course_test.rb @@ -3,15 +3,15 @@ require 'test_helper' class CourseTest < ActiveSupport::TestCase test 'fails with improper data' do assert_raise do - Course.create! course_number: nil, subject: nil, semester_id: nil + Course.create! course_number: nil, subject: nil end end test 'creates with proper data' do - Course.create! course_number: '112', subject: 'CS', semester_id: semesters(:fall2018).id + Course.create! course_number: '112', subject: 'CS' end test 'has correct number of sections' do - assert_equal 2, courses(:cs112).course_sections.count + assert_equal 3, courses(:cs112).course_sections.count end end diff --git a/schedules/test/models/semester_test.rb b/schedules/test/models/semester_test.rb index 624cfdec1d9e4a174d211f0bb12ba09af97cad4a..9c06415791580a2fc0860c1e81fb86e6b7a91f0b 100644 --- a/schedules/test/models/semester_test.rb +++ b/schedules/test/models/semester_test.rb @@ -10,8 +10,4 @@ class SemesterTest < ActiveSupport::TestCase test 'create successful' do Semester.create!(season: 'Test', year: 'Test') end - - test 'semester has correct number of courses' do - assert_equal 2, semesters(:fall2018).courses.count - end end