verso 0.0.9 → 0.0.10

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: d77111f7d6014a8e8c6895adb5fce355dec560ae
4
- data.tar.gz: 5358aaa41b752dec7dfacb6f041c920c5c00ae84
3
+ metadata.gz: 6cc8157c300f2bb76447aea7364fcc06456a837a
4
+ data.tar.gz: 7047e6972fb757fa0d37efc6658141051d08ccd2
5
5
  SHA512:
6
- metadata.gz: 8bc3d7d4ab6f4bf5b29fb4d314c50c51e67a90eb62819ff905885abd1382cc03e678a1124ff80416099cfc2fd7af2c97e4602942630dcac64885678265162729
7
- data.tar.gz: bf663a9bf8f9a497a87a9cb637753a932b774390665e662698cce90dc3ac21f3f8b67f38d95bac9922a56aa180b41fc0b5d9fa1a692674d83fab2939af42c9cb
6
+ metadata.gz: 296524656f995cd3119a199db8033dc0288850fc149eb2685b5cbd37dbe04e1e0c09513e16765c9ea0df8c5a3b4770380c907147cb7d54e0165ba7db6ad85328
7
+ data.tar.gz: 5a8032ba1ca5aafc5b7f9cd86c75381317c966ad4c5f6661a56d12143651255ffc6b9fd3c88d83487bb37363e3034677b836d10491b801f32f66ebe91c575e5e
data/README.md CHANGED
@@ -18,7 +18,7 @@ The verso gem has been tested with Ruby 2.0.0, 1.9.3, and 1.8.7.
18
18
 
19
19
  ## Quick Start
20
20
 
21
- The wrapper should make a great starting pointing for getting course,
21
+ The wrapper should make a great starting point for getting course,
22
22
  curriculum, and occupation data out of Verso. The classes available in
23
23
  lib/verso correspond to the resources described in the [API
24
24
  documentation](http://api.cteresource.org/docs). The usual points of entry
@@ -65,6 +65,91 @@ Search for Occupations, get back lists of "occupation data," i.e., a list of lis
65
65
  creds.first.title # => "Computer Programming (NOCTI)"
66
66
  creds.first.related_courses.last # => "Programming, Advanced"
67
67
 
68
+ ## New! verso-mt command line tool
69
+
70
+ verso-mt is a command line tool for generating the simpler sorts of CSV reports
71
+ from the CTE Resource Center Web API data. If you need to work on *collections*
72
+ of related resources -- all the occupations related to a course, say, or all
73
+ the courses related to a course, or all the credentials related to a course --
74
+ then verso-mt won't help. You'll need to write a script. But if you only need a
75
+ report from attributes on courses, credentials, or occupations, verso-mt
76
+ totally makes this easy. It will even let you reach into related objects -- an
77
+ occupation's pathway, say, or a credential's source.
78
+
79
+ You can see a help message by typing `verso-mt -h`. Three sorts of resources
80
+ can be fetched: course, credential, and occupation. Course is the default. Use
81
+ the -q option to specify query parameters. The parameters permissible are
82
+ discussed in the API documentation for CourseList, CredentialList, and
83
+ OccupationList. Separate the parameter from its value with a colon (:) and
84
+ separate multiple parameters with a plus (+), e.g. text:foo+edition:2013.
85
+ Filters, specified with the -f option are formed the same way, but are used by
86
+ verso-mt to filter out results after they're fetched from the server, based on
87
+ a fuzzy match against the specified attribute. Specify the columns you wish to
88
+ see in your CSV report with the -c option and a comma-separated list of
89
+ attributes. You can use dot notation to reach into a related object. E.g., `-c
90
+ title,source.title` could be used to get the title and source title for a list
91
+ of credentials.
92
+
93
+ Here are some examples:
94
+
95
+ ### Similar to examples/copyright_year.rb
96
+
97
+ In this example, we do not specify the resource. It defaults to course.
98
+
99
+ verso-mt -c title,code,frontmatter.copyright_year,related_resources
100
+
101
+ ### similar to examples/course_notes.rb
102
+
103
+ verso-mt -c code,title,notes
104
+
105
+ ### similar to examples/cpo.rb
106
+
107
+ Here we use the '-q' query parameter. You can send it any parameter mentioned
108
+ in the API documentation for the corresponding resource. Here we are sending a
109
+ wildcard (i.e., everything) in the text parameter for occupations.
110
+
111
+ verso-mt -r occupation -q text:* -c title,pathway.title,pathway.cluster.title
112
+
113
+ ### similar to examples/credential_cost.rb
114
+
115
+ verso-mt -r credential -c title,cost
116
+
117
+ ### similar to examples/credential_sources.rb
118
+
119
+ Note in this example, we are reaching into the source, a related object, using
120
+ dot notation.
121
+
122
+ verso-mt -r credential -c title,source.title,contractor_name
123
+
124
+ ### equivalent to examples/hours.rb
125
+
126
+ Note in this example, we are using '-f' the filtering option. We ask it to
127
+ filter out only courses that have 140 hours.
128
+
129
+ verso-mt -f hours:140 -c title,code,hours
130
+
131
+ ### equivalent to examples/hs_and_ms.rb
132
+
133
+ Note we are specifying two filters here.
134
+
135
+ verso-mt -f is_hs?:true+is_ms?:true
136
+
137
+ ### equivalent to examples/hs_v_ms.rb
138
+
139
+ verso-mt -c title,code,is_ms?,is_hs?
140
+
141
+ ### equivalent to examples/passing_score.rb
142
+
143
+ verso-mt -r credential -c title,source.title,passing_score
144
+
145
+ ### all the courses related to 'energy' in 2013 edition with 'technology' in title
146
+
147
+ verso-mt -r course -q text:energy+edition:2013 -f title:technology -c title,code,edition
148
+
149
+ ### search credentials for 'web' and return all where source title matches nocti
150
+
151
+ verso-mt -r credential -q text:web -f source.title:nocti -c title,source.title
152
+
68
153
  ## Additional Documentation
69
154
 
70
155
  * [http://api.cteresource.org/docs](http://api.cteresource.org/docs)
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env ruby
2
+ require 'csv'
3
+ require 'optparse'
4
+ require 'verso'
5
+
6
+ module Verso
7
+ module ChainableSend
8
+ # takes a string of dot-separated method names and recursively calls
9
+ # Object#send with each
10
+ def chained_send(chain)
11
+ messages = chain.split('.')
12
+ if messages.length == 1
13
+ respond_to?(chain) ? send(chain) : ''
14
+ else
15
+ send(messages.first).
16
+ extend(Verso::ChainableSend).
17
+ chained_send(messages.slice(1, messages.length).join('.'))
18
+ end
19
+ end
20
+ end
21
+
22
+ class OccupationList
23
+ private
24
+
25
+ # confusingly, OccupationList is actually a list of OccupationData obj's
26
+ # monkey patch so it behaves as expected for this script
27
+ alias_method :occupations_datas, :occupations
28
+ def occupations
29
+ occupations_datas.flat_map { |od| od.occupations }
30
+ end
31
+ end
32
+
33
+ class OptionBucket
34
+ attr_accessor :resource, :params, :filters, :columns
35
+ def initialize(opts={})
36
+ @resource = opts[:resource] || 'course'
37
+ @params = opts[:params] || {}
38
+ @filters = opts[:filters] || {}
39
+ @columns = opts[:columns] || ['title', 'code']
40
+ fill!(opts[:argv] || ARGV)
41
+ end
42
+
43
+ private
44
+
45
+ def fill!(argv)
46
+ parser = OptionParser.new do |opts|
47
+ opts.banner = 'Usage: verso [options]'
48
+
49
+ opts.on('-h', '--helper', 'Show this message.') do
50
+ puts opts
51
+ exit
52
+ end
53
+
54
+ opts.on('-r', '--resource RES', ['course', 'credential', 'occupation'],
55
+ 'API resource list to get',
56
+ 'One of: course, credential, occupation.') do |res|
57
+ @resource = res
58
+ end
59
+
60
+ opts.on(
61
+ '-c', '--columns COLS', Array,
62
+ 'Comma-separated list of resource attributes to display.') do |attrs|
63
+ @columns = attrs
64
+ end
65
+
66
+ opts.accept kv_pairs = Object.new do |val|
67
+ pairs = val.split('+')
68
+ raise OptionParser::InvalidArgument unless pairs.all? do |i|
69
+ i =~ /^[\w\s.\?]+:[\w\s.\*]+$/
70
+ end
71
+ pairs.inject({}) do |h, pair|
72
+ h[pair.split(':').first] = pair.split(':').last
73
+ h
74
+ end
75
+ end
76
+
77
+ opts.on(
78
+ '-f', '--filters FILTERS', kv_pairs,
79
+ 'Plus-separated list of colon-separated PROP:VALUE pairs.') do |f|
80
+ @filters = f
81
+ end
82
+
83
+ opts.on(
84
+ '-q', '--query PARAMS', kv_pairs,
85
+ 'Plus-separated list of colon-separated PARAM:VALUE pairs.',
86
+ 'Parameters should correspond to those in the resource docs.') do |p|
87
+ @params = p
88
+ end
89
+ end
90
+ parser.parse!(argv)
91
+ end
92
+ end
93
+
94
+ class MultiTool
95
+ attr_reader :options
96
+ def initialize(options)
97
+ @options = options
98
+ end
99
+
100
+ def klass
101
+ eval("Verso::#{options.resource.capitalize}List")
102
+ end
103
+
104
+ def resources
105
+ klass.new(options.params).collect do |r|
106
+ r.extend(Verso::ChainableSend)
107
+ end
108
+ end
109
+
110
+ def filtered_resources
111
+ resources.select do |resource|
112
+ options.filters.all? do |k, v|
113
+ resource.chained_send(k).to_s =~ Regexp.new(v, Regexp::IGNORECASE)
114
+ end
115
+ end
116
+ end
117
+
118
+ def run(&block)
119
+ block.call(options, filtered_resources)
120
+ end
121
+ end
122
+ end
123
+
124
+ begin
125
+ options = Verso::OptionBucket.new
126
+ rescue OptionParser::InvalidArgument => e
127
+ puts e
128
+ exit(1)
129
+ end
130
+
131
+ mt = Verso::MultiTool.new(options)
132
+ mt.run do |options, resources|
133
+ puts CSV.generate_line(
134
+ options.columns.
135
+ collect { |c| "#{options.resource.capitalize} #{c.capitalize}" }
136
+ )
137
+ resources.each do |resource|
138
+ puts CSV.generate_line(
139
+ options.columns.collect { |col| resource.chained_send(col) }
140
+ )
141
+ end
142
+ end
@@ -0,0 +1,17 @@
1
+ # usage: ruby associated_with.rb 'Title of a Standard'
2
+ #
3
+ # e.g., ruby associated_with.rb 'Science' # => all courses associated with
4
+ # the Science standards body.
5
+
6
+ require 'csv'
7
+ require 'verso'
8
+
9
+ standard = ARGV[0] || 'Science'
10
+
11
+ puts CSV.generate_line(%w{ Code Title }) + "\n"
12
+
13
+ Verso::CourseList.new.each do |c|
14
+ if c.standards.find { |c| c.title == standard }
15
+ puts CSV.generate_line([c.code, c.title])
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ # usage: ruby ceop.rb
2
+ #
3
+ # dumps CSV list of courses wth cluster, pathway, occupation information in CSV
4
+ # format.
5
+
6
+ require 'csv'
7
+ require 'verso'
8
+
9
+ puts CSV.generate_line(%w{ Title Code Edition Cluster Pathway Occupation })
10
+
11
+ Verso::CourseList.new.each do |c|
12
+ c.occupation_data.each do |od|
13
+ od.occupations.each do |occupation|
14
+ puts CSV.generate_line(
15
+ [c.title, c.code, c.edition, od.cluster.title,
16
+ od.pathway.title, occupation.title]
17
+ )
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # usage: ruby copyright_year.rb
2
+ #
3
+
4
+ require 'csv'
5
+ require 'verso'
6
+
7
+ puts CSV.generate_line(
8
+ %w(Program\ Area Title Code Copyright Related\ Resources)
9
+ )
10
+ courses = Verso::CourseList.new
11
+ courses.sort_by { |course| course.title }.each do |course|
12
+ course.attrs[:program_areas].each do |pa|
13
+ puts CSV.generate_line [
14
+ pa,
15
+ course.title,
16
+ course.code,
17
+ course.frontmatter ? course.frontmatter.copyright_year : '',
18
+ course.related_resources.join(', ')
19
+ ]
20
+ end
21
+ end
@@ -0,0 +1,10 @@
1
+ # usage: ruby course_notes.rb
2
+
3
+ require 'csv'
4
+ require 'verso'
5
+
6
+ Verso::CourseList.new.each do |course|
7
+ unless course.notes.to_s.empty?
8
+ puts CSV.generate_line([course.code, course.title, course.notes])
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ # usage: ruby cpo.rb
2
+ require 'csv'
3
+ require 'verso'
4
+
5
+ puts CSV.generate_line(%w(Occupation Pathway Cluster))
6
+ ods = Verso::OccupationList.new(:text => '*')
7
+ ods.each do |od|
8
+ od.occupations.each do |o|
9
+ puts CSV.generate_line [o.title, od.pathway.title, od.cluster.title]
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ # usage: ruby credential_cost.rb
2
+
3
+ require 'csv'
4
+ require 'verso'
5
+
6
+ puts CSV.generate_line(['Title', 'cost'])
7
+ Verso::CredentialList.new.each do |cred|
8
+ puts CSV.generate_line([cred.title, cred.cost])
9
+ end
@@ -0,0 +1,10 @@
1
+ # usage: ruby credential_sources.rb
2
+ #
3
+
4
+ require 'csv'
5
+ require 'verso'
6
+
7
+ puts CSV.generate_line(%w(Credential Source Contractor))
8
+ Verso::CredentialList.new.each do |cred|
9
+ puts CSV.generate_line([cred.title, cred.source.title, cred.contractor_name])
10
+ end
@@ -0,0 +1,25 @@
1
+ # usage: ruby credentials.rb
2
+
3
+ require 'csv'
4
+ require 'verso'
5
+
6
+ puts CSV.generate_line(
7
+ %w{ Title Description Source Contractor Related\ Courses }
8
+ )
9
+
10
+ Verso::CredentialList.new.each do |cred|
11
+ puts CSV.generate_line(
12
+ [cred.title,
13
+ cred.description.
14
+ gsub(/<\/?[^>]*>/, "").
15
+ strip.
16
+ gsub(/\r\n/, " | ").
17
+ gsub(/&[a-zA-Z]+;/, " "),
18
+ cred.source.title,
19
+ cred.contractor_name,
20
+ cred.
21
+ related_courses.
22
+ collect { |c| "#{c.title} (#{c.code})" }.
23
+ join('; ')]
24
+ )
25
+ end
@@ -0,0 +1,12 @@
1
+ # usage: ruby hours.rb NN
2
+
3
+ require 'csv'
4
+ require 'verso'
5
+
6
+ hours = ARGV[0].to_i
7
+ Verso::CourseList.new.
8
+ select { |c| c.hours == hours }.
9
+ sort_by { |c| c.title }.
10
+ each do |course|
11
+ puts CSV.generate_line [course.title, course.code]
12
+ end
@@ -0,0 +1,9 @@
1
+ # usage: ruby hs_and_ms.rb
2
+
3
+ require 'verso'
4
+
5
+ Verso::CourseList.new.each do |course|
6
+ if course.is_hs? && course.is_ms?
7
+ puts "#{course.title} (#{course.code})"
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ # usage: ruby hs_v_ms.rb
2
+
3
+ require 'csv'
4
+ require 'verso'
5
+
6
+ Verso::CourseList.new.sort_by { |c| c.title + c.code }.each do |course|
7
+ puts CSV.generate_line(
8
+ ["#{course.title} (#{course.code})",
9
+ course.is_ms? && !course.is_hs? ? "MIDDLE" : "HIGH"]
10
+ )
11
+ end
@@ -0,0 +1,18 @@
1
+ # usage: ruby pa_course_code_cluster_pathway.rb
2
+ #
3
+ # courses with clusters/pathways by (deprecated) program areas
4
+ require 'csv'
5
+ require 'verso'
6
+
7
+ puts CSV.generate_line(%w{ Program\ Area Title Code Cluster Pathway })
8
+
9
+ Verso::ProgramAreaList.new.each do |pa|
10
+ pa.courses.each do |course|
11
+ course.occupation_data.each do |od|
12
+ puts CSV.generate_line(
13
+ [pa.title, course.title, course.code,
14
+ od.cluster.title, od.pathway.title]
15
+ )
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # usage: ruby passing_score.rob
2
+ #
3
+ # list of credentials with passing score where available
4
+ require 'csv'
5
+ require 'verso'
6
+
7
+ puts CSV.generate_line(['Title', 'Source', 'Passing Score'])
8
+ Verso::CredentialList.new.each do |cred|
9
+ unless (cred.passing_score.to_s.empty? ||
10
+ cred.passing_score.to_s =~ /contact/i)
11
+ puts CSV.generate_line([cred.title, cred.source.title, cred.passing_score])
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ #usage: ruby related_courses.rb
2
+ #
3
+ # list of each course and the codes of its related courses
4
+ require 'csv'
5
+ require 'verso'
6
+
7
+ puts CSV.generate_line(%w{ Code Title Related\ Courses })
8
+
9
+ Verso::CourseList.new.each do |course|
10
+ puts CSV.generate_line(
11
+ [course.code, course.title,
12
+ course.related_courses.collect { |c| c.code }.join(' ')]
13
+ )
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Verso
2
- VERSION = "0.0.9"
2
+ VERSION = "0.0.10"
3
3
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
  s.add_runtime_dependency 'json'
21
- s.add_runtime_dependency 'addressable'
21
+ s.add_runtime_dependency 'addressable', '~> 2.3.5'
22
22
  s.add_development_dependency "webmock"
23
23
  s.add_development_dependency "redcarpet"
24
24
  s.add_development_dependency "rspec"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: verso
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lee Capps
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-06 00:00:00.000000000 Z
11
+ date: 2013-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: addressable
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 2.3.5
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 2.3.5
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: webmock
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -111,7 +111,8 @@ dependencies:
111
111
  description: A Ruby wrapper for the Virginia CTE Resource Center's Web API
112
112
  email:
113
113
  - himself@leecapps.com
114
- executables: []
114
+ executables:
115
+ - verso-mt
115
116
  extensions: []
116
117
  extra_rdoc_files: []
117
118
  files:
@@ -120,6 +121,21 @@ files:
120
121
  - LICENSE.md
121
122
  - README.md
122
123
  - Rakefile
124
+ - bin/verso-mt
125
+ - examples/associated_with.rb
126
+ - examples/ceop.rb
127
+ - examples/copyright_year.rb
128
+ - examples/course_notes.rb
129
+ - examples/cpo.rb
130
+ - examples/credential_cost.rb
131
+ - examples/credential_sources.rb
132
+ - examples/credentials.rb
133
+ - examples/hours.rb
134
+ - examples/hs_and_ms.rb
135
+ - examples/hs_v_ms.rb
136
+ - examples/pa_course_code_cluster_pathway.rb
137
+ - examples/passing_score.rb
138
+ - examples/related_courses.rb
123
139
  - lib/verso.rb
124
140
  - lib/verso/base.rb
125
141
  - lib/verso/cluster.rb
@@ -200,7 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
200
216
  version: '0'
201
217
  requirements: []
202
218
  rubyforge_project: verso
203
- rubygems_version: 2.0.0
219
+ rubygems_version: 2.0.3
204
220
  signing_key:
205
221
  specification_version: 4
206
222
  summary: Verso API wrapper