lse_courses 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 86c640247013f44f18ba17e7abc6fa037e498e44
4
- data.tar.gz: acd3967aac16df1b85f268cb092c34bf8b7bf58a
3
+ metadata.gz: c7c9c9889a37a6207cd6532c6c8dd9063848fcc6
4
+ data.tar.gz: 176a2d786f26fa542c74b811376165016f762e21
5
5
  SHA512:
6
- metadata.gz: 553d717bfbf3cf480786afcd364c41d65d421335933bb7f0697ddfbd908dbff4a0014668b81bc7efee4bbfce77f13d7711ef7e2b565ea4edee898c70cd1de656
7
- data.tar.gz: a906cc99a9718f5545ba6bec3a2fa859b0170c31efc5536de711745c5af84ec2aa22d8c6d547c6b492bb11ee31808b9f724fbb669997685bbd374bef1c7c2dfd
6
+ metadata.gz: b7dd7f44f21af449cd850f376920ac5ae3e003eabb660f90fb6ecd252fb6bc97bb8373218e5f41747e734d1e616afd5597cc0cfed867875e60ce90bcabcfc26e
7
+ data.tar.gz: 2002eff56b061d4953db574ff339f3251b3eb13d37794bd667986ae04731b87ebffe358f1d804b1424dcce871c7853fc1d5b1a244dd9656e6be38e6565199681
data/README.md CHANGED
@@ -9,7 +9,12 @@ something along the line of [YalePlus](http://yaleplus.com/)'s Bluebook+.
9
9
 
10
10
  Add the gem to your Gemfile, then run `bundle install`:
11
11
 
12
- ```
12
+ ```ruby
13
+ # Install from RubyGems
14
+ source "http://rubygems.org"
15
+ gem 'lse_courses', '0.0.3'
16
+
17
+ # Install the latest version via Git
13
18
  gem 'lse_courses', git: 'git@github.com:timrogers/lse_courses.git'
14
19
  ```
15
20
 
@@ -19,10 +24,19 @@ dependent on your setup.
19
24
  You can retrieve an array with every course offered at LSE:
20
25
 
21
26
  ```ruby
27
+ # You can just fetch the most basic information - name, code and type (e.g. undergraduate)
22
28
  courses = LSECourses::Course.all
29
+
30
+ # ...or you can grab everything at once - this will take a long time
31
+ courses = LSECourses::Course.all(preload: true)
32
+
23
33
  courses.each do |course|
24
34
  puts "#{course.code} - #{course.name}"
25
35
 
36
+ # Fetch a more detailed attribute, and we'll grab all of them for you
37
+ # and store them if you didn't preload the data originally
38
+ puts course.department
39
+
26
40
  # LSE records include surveys on courses - stored in #survey on the object
27
41
  puts "#{course.survey.recommended_by}% of students recommend this cause"
28
42
  end
@@ -31,8 +45,11 @@ end
31
45
  ...or you can fetch a specific course by code:
32
46
 
33
47
  ```ruby
34
- course = LSECourses::Course.find_by_code("LSE100")
48
+ course = LSECourses::Course.find("LSE100")
35
49
  puts course.name
50
+
51
+ # All the data is loaded straight up, since there's only one course to fetch
52
+ puts course.department
36
53
  ```
37
54
 
38
55
  Upcoming features that should be added are some kind of search (e.g. for
@@ -1,16 +1,167 @@
1
- require 'active_support/core_ext/object/try'
2
1
  require 'nokogiri'
3
2
 
4
3
  module LSECourses
5
4
  class Course
6
- attr_reader :code, :name, :department, :students, :average_class_size,
7
- :value, :assessments, :teachers, :availability, :prerequisites,
8
- :content, :teaching, :formative_coursework, :reading, :type, :survey
5
+ attr_reader :code, :name, :type
6
+ attr_accessor :url
9
7
 
10
8
  def initialize(opts = {})
11
9
  opts.each { |k, v| instance_variable_set("@#{k}", v) }
12
10
  end
13
11
 
12
+ def fetch_attributes
13
+ page = self.class.fetch_and_parse(url)
14
+ key_facts = page.css('#keyFacts-Content p')
15
+
16
+ @survey = if page.css('#survey-Label').any?
17
+ SurveyResult.new(
18
+ response_rate: page.css('#survey-Label-2 span').text.gsub("Response rate: ", "").gsub("%", "").to_f,
19
+ recommended_by: page.css('#survey-Content-Recommend p')[1].text.gsub("%", "").to_f,
20
+ reading_list: page.css('#survey-Content table tbody td')[1].text.to_f,
21
+ materials: page.css('#survey-Content table tbody td')[3].text.to_f,
22
+ satisfied: page.css('#survey-Content table tbody td')[5].text.to_f,
23
+ lectures: page.css('#survey-Content table tbody td')[7].text.to_f,
24
+ integration: page.css('#survey-Content table tbody td')[9].text.to_f,
25
+ contact: page.css('#survey-Content table tbody td')[11].text.to_f,
26
+ feedback: page.css('#survey-Content table tbody td')[13].text.to_f,
27
+ )
28
+ end
29
+
30
+ @code = page.css('#courseCode').text
31
+ @name = page.css('span#title').text
32
+ @department = key_facts[0].text.gsub("Department: ", "")
33
+ @students = key_facts[1].text.gsub("Total students 2012/13:", "").to_i
34
+ @average_class_size = key_facts[2].text.gsub("Average class size 2012/13: ", "").to_i
35
+ @value = key_facts[3].text.gsub("Value: ", "")
36
+ @assessments = self.class.join_p_tags(page.css('#assessment-Content p'))
37
+ @teachers = self.class.join_p_tags(page.css('#teacherResponsible-Content p'))
38
+ @availability = self.class.join_p_tags(page.css('#availability-Content p'))
39
+ @prerequisites = self.class.join_p_tags(page.css('#preRequisites-Content p'))
40
+ @content = self.class.join_p_tags(page.css('#courseContent-Content p'))
41
+ @teaching = self.class.join_p_tags(page.css('#teaching-Content p'))
42
+ @formative_coursework = self.class.join_p_tags(page.css('#formativeCoursework-Content p'))
43
+ @reading = self.class.join_p_tags(page.css('#indicativeReading-Content p'))
44
+
45
+ self
46
+ end
47
+
48
+ def department
49
+ if @department
50
+ @department
51
+ else
52
+ fetch_attributes
53
+ @department
54
+ end
55
+ end
56
+
57
+ def students
58
+ if @students
59
+ @students
60
+ else
61
+ fetch_attributes
62
+ @students
63
+ end
64
+ end
65
+
66
+ def average_class_size
67
+ if @average_class_size
68
+ @average_class_size
69
+ else
70
+ fetch_attributes
71
+ @average_class_size
72
+ end
73
+ end
74
+
75
+ def value
76
+ if @value
77
+ @value
78
+ else
79
+ fetch_attributes
80
+ @value
81
+ end
82
+ end
83
+
84
+ def assessments
85
+ if @assessments
86
+ @assessments
87
+ else
88
+ fetch_attributes
89
+ @assessments
90
+ end
91
+ end
92
+
93
+ def teachers
94
+ if @teachers
95
+ @teachers
96
+ else
97
+ fetch_attributes
98
+ @teachers
99
+ end
100
+ end
101
+
102
+ def availability
103
+ if @availability
104
+ @availability
105
+ else
106
+ fetch_attributes
107
+ @availability
108
+ end
109
+ end
110
+
111
+ def prerequisites
112
+ if @prerequisites
113
+ @prerequisites
114
+ else
115
+ fetch_attributes
116
+ @prerequisites
117
+ end
118
+ end
119
+
120
+ def content
121
+ if @content
122
+ @content
123
+ else
124
+ fetch_attributes
125
+ @content
126
+ end
127
+ end
128
+
129
+ def teaching
130
+ if @teaching
131
+ @teaching
132
+ else
133
+ fetch_attributes
134
+ @teaching
135
+ end
136
+ end
137
+
138
+ def formative_coursework
139
+ if @formative_coursework
140
+ @formative_coursework
141
+ else
142
+ fetch_attributes
143
+ @formative_coursework
144
+ end
145
+ end
146
+
147
+ def reading
148
+ if @reading
149
+ @reading
150
+ else
151
+ fetch_attributes
152
+ @reading
153
+ end
154
+ end
155
+
156
+ def survey
157
+ if @survey
158
+ @survey
159
+ else
160
+ fetch_attributes
161
+ @survey
162
+ end
163
+ end
164
+
14
165
  def undergraduate?
15
166
  type == "Undergraduate"
16
167
  end
@@ -25,8 +176,7 @@ module LSECourses
25
176
 
26
177
  # Checks if this module is available to General Course students
27
178
  def general_course?
28
- general_course_list = open("http://www.lse.ac.uk/resources/calendar/GeneralCourse/coursesNotAvailableToGeneralCStudents.htm")
29
- !general_course_list.read.include? code
179
+ !self.class.general_course_page.include? code
30
180
  end
31
181
 
32
182
  def survey?
@@ -45,22 +195,31 @@ module LSECourses
45
195
  }
46
196
  end
47
197
 
48
- def self.all
198
+ def self.all(options = {})
199
+ defaults = { preload: false }
200
+ options = defaults.merge(options)
201
+
49
202
  results = []
50
203
 
51
204
  course_lists.each_pair do |type, url|
52
205
  document = fetch_and_parse(url)
53
206
  document.css('table tr td p a').each do |link|
54
- course_url = URI.join(URI.parse(url), URI.parse(link['href'])).to_s
207
+ abstract = link.text.split(" ")
55
208
 
56
- course = fetch_and_parse course_url
57
- key_facts = course.css('#keyFacts-Content p')
58
- code = course.css('#courseCode').text
209
+ course_code = abstract.shift
210
+ name = abstract.join(" ")
211
+ course_url = URI.join(URI.parse(url), URI.parse(link['href'])).to_s
59
212
 
60
- results << course_page_to_object(course, type)
213
+ results << self.new(
214
+ url: course_url,
215
+ name: name,
216
+ code: course_code,
217
+ type: type
218
+ )
61
219
  end
62
220
  end
63
221
 
222
+ results.each(&:fetch_attributes) if options[:preload]
64
223
  results
65
224
  end
66
225
 
@@ -68,15 +227,19 @@ module LSECourses
68
227
  course_lists.each_pair do |type, url|
69
228
  document = fetch_and_parse(url)
70
229
  document.css('table tr td p a').each do |link|
71
- title = link.text
72
- course_code = title.split(" ").first
230
+ abstract = link.text.split(" ")
73
231
 
74
- if code == course_code
75
- course = fetch_and_parse(
76
- URI.join(URI.parse(url), URI.parse(link['href'])).to_s
77
- )
232
+ course_code = abstract.shift
233
+ name = abstract.join(" ")
234
+ course_url = URI.join(URI.parse(url), URI.parse(link['href'])).to_s
78
235
 
79
- return course_page_to_object(course, type)
236
+ if code == course_code
237
+ return self.new(
238
+ url: course_url,
239
+ name: name,
240
+ code: course_code,
241
+ type: type
242
+ ).fetch_attributes
80
243
  end
81
244
  end
82
245
  end
@@ -84,49 +247,18 @@ module LSECourses
84
247
  nil
85
248
  end
86
249
 
87
- def self.course_page_to_object(page, type)
88
- key_facts = page.css('#keyFacts-Content p')
89
-
90
- survey_result = if page.css('#survey-Label').any?
91
- SurveyResult.new(
92
- response_rate: page.css('#survey-Label-2 span').text.gsub("Response rate: ", "").gsub("%", "").to_f,
93
- recommended_by: page.css('#survey-Content-Recommend p')[1].text.gsub("%", "").to_f,
94
- reading_list: page.css('#survey-Content table tbody td')[1].text.to_f,
95
- materials: page.css('#survey-Content table tbody td')[3].text.to_f,
96
- satisfied: page.css('#survey-Content table tbody td')[5].text.to_f,
97
- lectures: page.css('#survey-Content table tbody td')[7].text.to_f,
98
- integration: page.css('#survey-Content table tbody td')[9].text.to_f,
99
- contact: page.css('#survey-Content table tbody td')[11].text.to_f,
100
- feedback: page.css('#survey-Content table tbody td')[13].text.to_f,
101
- )
102
- end
103
-
104
- self.new(
105
- type: type,
106
- code: page.css('#courseCode').text,
107
- name: page.css('span#title').text,
108
- department: key_facts[0].text.gsub("Department: ", ""),
109
- students: key_facts[1].text.gsub("Total students 2012/13:", "").to_i,
110
- average_class_size: key_facts[2].text.gsub("Average class size 2012/13: ", "").to_i,
111
- value: key_facts[3].text.gsub("Value: ", ""),
112
- assessments: join_p_tags(page.css('#assessment-Content p')),
113
- teachers: join_p_tags(page.css('#teacherResponsible-Content p')),
114
- availability: join_p_tags(page.css('#availability-Content p')),
115
- prerequisites: join_p_tags(page.css('#preRequisites-Content p')),
116
- content: join_p_tags(page.css('#courseContent-Content p')),
117
- teaching: join_p_tags(page.css('#teaching-Content p')),
118
- formative_coursework: join_p_tags(page.css('#formativeCoursework-Content p')),
119
- reading: join_p_tags(page.css('#indicativeReading-Content p')),
120
- survey: survey_result
121
- )
122
- end
123
-
124
250
  def self.join_p_tags(elements)
125
251
  elements.map(&:text).join("\n").strip
126
252
  end
127
253
 
254
+ def self.general_course_page
255
+ @general_course_page ||= open("http://www.lse.ac.uk/resources/calendar/GeneralCourse/coursesNotAvailableToGeneralCStudents.htm").read
256
+ end
257
+
128
258
  def self.fetch_and_parse(url)
129
259
  Nokogiri::HTML(open(url, &:read), 'UTF-8')
130
260
  end
261
+
262
+ self.singleton_class.send(:alias_method, :find, :find_by_code)
131
263
  end
132
264
  end
@@ -1,3 +1,3 @@
1
1
  module LSECourses
2
- VERSION = "0.0.2".freeze
2
+ VERSION = "0.0.3".freeze
3
3
  end
@@ -18,5 +18,4 @@ Gem::Specification.new do |spec|
18
18
  spec.require_paths = ["lib"]
19
19
 
20
20
  spec.add_runtime_dependency "nokogiri"
21
- spec.add_runtime_dependency "activesupport"
22
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lse_courses
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Rogers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-21 00:00:00.000000000 Z
11
+ date: 2014-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: activesupport
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - '>='
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
27
  description: Access to data on courses at the London School of Economics and Political
42
28
  Science (LSE)
43
29
  email: