explorecourses 0.0.1 → 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +59 -0
- data/explorecourses.gemspec +17 -0
- data/lib/explorecourses.rb +5 -0
- data/lib/explorecourses/base.rb +111 -0
- data/lib/explorecourses/course.rb +25 -0
- data/lib/explorecourses/instructor.rb +18 -0
- data/lib/explorecourses/schedule.rb +19 -0
- data/lib/explorecourses/section.rb +32 -0
- metadata +40 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c224e6b907a6b894da50ac2e36c92b2ff4640f93
|
4
|
+
data.tar.gz: 749be8eb5a1c35dc381a26a48ff0aa20eae04b67
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 412639c4c7166f257437b7a2f4348b55dbe03fc422c2e16a4e1931ddbb142dc3878a039b68cc02ec5fd070f365a103e58b5df1d1728f7d1e04f20e7fe756e052
|
7
|
+
data.tar.gz: 5a46fba6bc7059f8a5ecde84648c0f565bbeacd5049676813f3c0d7a7b0afdfc9d4de02d551a8b237682d38eeb3c058840fb1d9b03d6f3ccf7325a576255ac0f
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
### ExploreCourses for Ruby
|
2
|
+
|
3
|
+
##### Installation
|
4
|
+
|
5
|
+
Assuming that you have RubyGems, either run
|
6
|
+
|
7
|
+
gem install explorecourses
|
8
|
+
|
9
|
+
to install for your system or add the following to your Gemfile
|
10
|
+
|
11
|
+
gem 'explorecourses'
|
12
|
+
|
13
|
+
then run
|
14
|
+
|
15
|
+
bundle install
|
16
|
+
|
17
|
+
##### Usage
|
18
|
+
|
19
|
+
Until I add documentation annotations to the source code, I recommend reading the source directly to find out what properties can be accessed.
|
20
|
+
|
21
|
+
require 'explorecourses'
|
22
|
+
|
23
|
+
# Search for all the courses
|
24
|
+
courses = ExploreCourses.query_courses("CS 140")
|
25
|
+
|
26
|
+
# Get the title of the course
|
27
|
+
courses[0].title
|
28
|
+
=> "Operating Systems and Systems Programming"
|
29
|
+
|
30
|
+
# Get the number of sections for the course
|
31
|
+
courses[0].sections.length
|
32
|
+
=> 3
|
33
|
+
|
34
|
+
##### Checklist
|
35
|
+
|
36
|
+
* Add RDoc style documentation to all source code
|
37
|
+
* Add tests
|
38
|
+
|
39
|
+
##### License
|
40
|
+
|
41
|
+
Copyright (c) 2014 Roger Chen
|
42
|
+
|
43
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
44
|
+
of this software and associated documentation files (the "Software"), to deal
|
45
|
+
in the Software without restriction, including without limitation the rights
|
46
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
47
|
+
copies of the Software, and to permit persons to whom the Software is
|
48
|
+
furnished to do so, subject to the following conditions:
|
49
|
+
|
50
|
+
The above copyright notice and this permission notice shall be included in
|
51
|
+
all copies or substantial portions of the Software.
|
52
|
+
|
53
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
54
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
55
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
56
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
57
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
58
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
59
|
+
THE SOFTWARE.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'explorecourses'
|
3
|
+
s.version = '0.1'
|
4
|
+
s.date = '2014-09-26'
|
5
|
+
s.summary = 'Ruby wrapper for ExploreCourses API'
|
6
|
+
s.description = 'Allow Ruby programs to easily access the ExploreCourses API'
|
7
|
+
s.authors = ['Roger Chen']
|
8
|
+
s.email = 'rogerthechen@gmail.com'
|
9
|
+
s.homepage = 'https://rogr.me/projects/explorecourses-gem'
|
10
|
+
s.license = 'MIT'
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.require_path = 'lib'
|
14
|
+
|
15
|
+
s.add_dependency "nokogiri", "~> 1.6"
|
16
|
+
s.add_dependency "typhoeus", "~> 0.6"
|
17
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'typhoeus'
|
3
|
+
|
4
|
+
module ExploreCourses
|
5
|
+
|
6
|
+
URL_BASE_SEARCH = "http://explorecourses.stanford.edu/search?"
|
7
|
+
XML_VERSION = "xml-20140630"
|
8
|
+
|
9
|
+
def self.check_xml_version
|
10
|
+
request = Typhoeus::Request.new(URL_BASE_SEARCH, params: { view: XML_VERSION })
|
11
|
+
request.run
|
12
|
+
response = request.response
|
13
|
+
if response
|
14
|
+
doc = Nokogiri::XML(response.body)
|
15
|
+
return { deprecated: doc.at_xpath("//deprecated").content,
|
16
|
+
latest_version: doc.at_xpath("//latestVersion").content}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.query_courses(query)
|
21
|
+
params = {
|
22
|
+
view: XML_VERSION,
|
23
|
+
q: query
|
24
|
+
}
|
25
|
+
request = Typhoeus::Request.new(URL_BASE_SEARCH, params: params)
|
26
|
+
request.run
|
27
|
+
response = request.response
|
28
|
+
if response
|
29
|
+
doc = Nokogiri::XML(response.body)
|
30
|
+
# use XPath to navigate the XML body
|
31
|
+
courses_xml = doc.xpath(".//course")
|
32
|
+
courses = []
|
33
|
+
courses_xml.each do |course_xml|
|
34
|
+
year = course_xml.at_xpath(".//year").content
|
35
|
+
subject = course_xml.at_xpath(".//subject").content
|
36
|
+
code = course_xml.at_xpath(".//code").content
|
37
|
+
title = course_xml.at_xpath(".//title").content
|
38
|
+
description = course_xml.at_xpath(".//description").content
|
39
|
+
gers = course_xml.at_xpath(".//gers").content
|
40
|
+
repeatable = course_xml.at_xpath(".//repeatable").content
|
41
|
+
grading = course_xml.at_xpath(".//grading").content
|
42
|
+
units_min = course_xml.at_xpath(".//unitsMin").content
|
43
|
+
units_max = course_xml.at_xpath(".//unitsMax").content
|
44
|
+
sections = retrieve_sections(course_xml.xpath(".//section"))
|
45
|
+
courses << Course.new(year, subject, code, title, description, gers, repeatable,
|
46
|
+
grading, units_min, units_max, sections)
|
47
|
+
end
|
48
|
+
return courses
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def self.retrieve_sections(sections_xml)
|
55
|
+
sections = []
|
56
|
+
sections_xml.each do |section_xml|
|
57
|
+
class_id = section_xml.at_xpath(".//classId").content
|
58
|
+
term = section_xml.at_xpath(".//term").content
|
59
|
+
term_id = section_xml.at_xpath(".//termId").content
|
60
|
+
subject = section_xml.at_xpath(".//subject").content
|
61
|
+
code = section_xml.at_xpath(".//code").content
|
62
|
+
units = section_xml.at_xpath(".//units").content
|
63
|
+
section_number = section_xml.at_xpath(".//sectionNumber").content
|
64
|
+
component = section_xml.at_xpath(".//component").content
|
65
|
+
num_enrolled = section_xml.at_xpath(".//numEnrolled").content
|
66
|
+
max_enrolled = section_xml.at_xpath(".//maxEnrolled").content
|
67
|
+
num_waitlist = section_xml.at_xpath(".//numWaitlist").content
|
68
|
+
max_waitlist = section_xml.at_xpath(".//maxWaitlist").content
|
69
|
+
enroll_status = section_xml.at_xpath(".//enrollStatus").content
|
70
|
+
add_consent = section_xml.at_xpath(".//addConsent").content
|
71
|
+
drop_consent = section_xml.at_xpath(".//dropConsent").content
|
72
|
+
course_id = section_xml.at_xpath(".//courseId").content
|
73
|
+
schedules = retrieve_schedules(section_xml.xpath(".//schedule"))
|
74
|
+
sections << Section.new(class_id, term, term_id, subject, code, units, section_number, component,
|
75
|
+
num_enrolled, max_enrolled, num_waitlist, max_waitlist, enroll_status, add_consent,
|
76
|
+
drop_consent, course_id, schedules)
|
77
|
+
end
|
78
|
+
return sections
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.retrieve_schedules(schedules_xml)
|
82
|
+
schedules = []
|
83
|
+
schedules_xml.each do |schedule_xml|
|
84
|
+
start_date = schedule_xml.at_xpath(".//startDate").content
|
85
|
+
end_date = schedule_xml.at_xpath(".//endDate").content
|
86
|
+
start_time = schedule_xml.at_xpath(".//startTime").content
|
87
|
+
end_time = schedule_xml.at_xpath(".//endTime").content
|
88
|
+
location = schedule_xml.at_xpath(".//location").content
|
89
|
+
# Cleaning up after whoever put all the \t and \n in the string...
|
90
|
+
days = schedule_xml.at_xpath("./days").content.gsub(/[\t\n]/, ' ').split.join(',')
|
91
|
+
instructors = retrieve_instructors(schedule_xml.xpath(".//instructor"))
|
92
|
+
schedules << Schedule.new(start_date, end_date, start_time, end_time, location, days, instructors)
|
93
|
+
end
|
94
|
+
return schedules
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.retrieve_instructors(instructors_xml)
|
98
|
+
instructors = []
|
99
|
+
instructors_xml.each do |instructor_xml|
|
100
|
+
name = instructor_xml.at_xpath(".//name").content
|
101
|
+
first_name = instructor_xml.at_xpath(".//firstName").content
|
102
|
+
middle_name = instructor_xml.at_xpath(".//middleName").content
|
103
|
+
last_name = instructor_xml.at_xpath(".//lastName").content
|
104
|
+
sunet = instructor_xml.at_xpath(".//sunet").content
|
105
|
+
role = instructor_xml.at_xpath(".//role").content
|
106
|
+
instructors << Instructor.new(name, first_name, middle_name, last_name, sunet, role)
|
107
|
+
end
|
108
|
+
return instructors
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ExploreCourses
|
2
|
+
|
3
|
+
class Course
|
4
|
+
|
5
|
+
def initialize(year, subject, code, title, description, gers, repeatable, grading, units_min,
|
6
|
+
units_max, sections)
|
7
|
+
@year = year
|
8
|
+
@subject = subject
|
9
|
+
@code = code
|
10
|
+
@title = title
|
11
|
+
@description = description
|
12
|
+
@gers = gers
|
13
|
+
@repeatable = repeatable
|
14
|
+
@grading = grading
|
15
|
+
@units_min = units_min
|
16
|
+
@units_max = units_max
|
17
|
+
@sections = sections
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :year, :subject, :code, :title, :description, :gers, :repeatable, :grading, :units_min,
|
21
|
+
:units_max, :sections
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ExploreCourses
|
2
|
+
|
3
|
+
class Instructor
|
4
|
+
|
5
|
+
def initialize(name, first_name, middle_name, last_name, sunet, role)
|
6
|
+
@name = name
|
7
|
+
@first_name = first_name
|
8
|
+
@middle_name = middle_name
|
9
|
+
@last_name = last_name
|
10
|
+
@sunet = sunet
|
11
|
+
@role = role
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :name, :first_name, :middle_name, :last_name, :sunet, :role
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ExploreCourses
|
2
|
+
|
3
|
+
class Schedule
|
4
|
+
|
5
|
+
def initialize(start_date, end_date, start_time, end_time, location, days, instructors)
|
6
|
+
@start_date = start_date
|
7
|
+
@end_date = end_date
|
8
|
+
@start_time = start_time
|
9
|
+
@end_time = end_time
|
10
|
+
@location = location
|
11
|
+
@days = days
|
12
|
+
@instructors = instructors
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :start_date, :end_date, :start_time, :end_time, :location, :days, :instructors
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ExploreCourses
|
2
|
+
|
3
|
+
class Section
|
4
|
+
|
5
|
+
def initialize(class_id, term, term_id, subject, code, units, section_number, component, num_enrolled,
|
6
|
+
max_enrolled, num_waitlist, max_waitlist, enroll_status, add_consent, drop_consent, course_id, schedules)
|
7
|
+
@class_id = class_id
|
8
|
+
@term = term
|
9
|
+
@term_id = term_id
|
10
|
+
@subject = subject
|
11
|
+
@code = code
|
12
|
+
@units = units
|
13
|
+
@section_number = section_number
|
14
|
+
@component = component
|
15
|
+
@num_enrolled = num_enrolled
|
16
|
+
@max_enrolled = max_enrolled
|
17
|
+
@num_waitlist = num_waitlist
|
18
|
+
@max_waitlist = max_waitlist
|
19
|
+
@enroll_status = enroll_status
|
20
|
+
@add_consent = add_consent
|
21
|
+
@drop_consent = drop_consent
|
22
|
+
@course_id = course_id
|
23
|
+
@schedules = schedules
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :class_id, :term, :term_id, :subject, :code, :units, :section_number, :component,
|
27
|
+
:num_enrolled, :max_enrolled, :num_waitlist, :max_waitlist, :enroll_status, :add_consent,
|
28
|
+
:drop_consent, :course_id, :schedules
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: explorecourses
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.1'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roger Chen
|
@@ -9,13 +9,50 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2014-09-26 00:00:00.000000000 Z
|
12
|
-
dependencies:
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: typhoeus
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.6'
|
13
41
|
description: Allow Ruby programs to easily access the ExploreCourses API
|
14
42
|
email: rogerthechen@gmail.com
|
15
43
|
executables: []
|
16
44
|
extensions: []
|
17
45
|
extra_rdoc_files: []
|
18
|
-
files:
|
46
|
+
files:
|
47
|
+
- ".gitignore"
|
48
|
+
- README.md
|
49
|
+
- explorecourses.gemspec
|
50
|
+
- lib/explorecourses.rb
|
51
|
+
- lib/explorecourses/base.rb
|
52
|
+
- lib/explorecourses/course.rb
|
53
|
+
- lib/explorecourses/instructor.rb
|
54
|
+
- lib/explorecourses/schedule.rb
|
55
|
+
- lib/explorecourses/section.rb
|
19
56
|
homepage: https://rogr.me/projects/explorecourses-gem
|
20
57
|
licenses:
|
21
58
|
- MIT
|