verso 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.md +10 -22
- data/lib/verso.rb +10 -2
- data/lib/verso/base.rb +50 -0
- data/lib/verso/cluster.rb +55 -25
- data/lib/verso/cluster_list.rb +15 -10
- data/lib/verso/correlation_list.rb +30 -40
- data/lib/verso/course.rb +106 -43
- data/lib/verso/course_list.rb +57 -21
- data/lib/verso/credential.rb +94 -20
- data/lib/verso/credential_list.rb +30 -15
- data/lib/verso/duty_area.rb +23 -10
- data/lib/verso/edition_list.rb +18 -10
- data/lib/verso/emphasis.rb +26 -12
- data/lib/verso/emphasis_list.rb +18 -10
- data/lib/verso/examination_list.rb +28 -12
- data/lib/verso/extra.rb +34 -32
- data/lib/verso/extras_list.rb +28 -12
- data/lib/verso/frontmatter.rb +43 -11
- data/lib/verso/hash.rb +19 -0
- data/lib/verso/http_gettable.rb +31 -0
- data/lib/verso/occupation.rb +36 -14
- data/lib/verso/occupation_data.rb +35 -14
- data/lib/verso/occupation_list.rb +23 -20
- data/lib/verso/pathway.rb +32 -14
- data/lib/verso/program_area.rb +42 -21
- data/lib/verso/program_area_list.rb +15 -11
- data/lib/verso/standard.rb +45 -23
- data/lib/verso/standards_list.rb +41 -30
- data/lib/verso/task.rb +52 -17
- data/lib/verso/task_list.rb +40 -17
- data/lib/verso/version.rb +1 -1
- data/spec/cluster_list_spec.rb +78 -5
- data/spec/cluster_spec.rb +106 -9
- data/spec/correlation_list_spec.rb +108 -50
- data/spec/course_list_spec.rb +112 -23
- data/spec/course_spec.rb +321 -127
- data/spec/credential_list_spec.rb +83 -52
- data/spec/credential_spec.rb +358 -19
- data/spec/duty_area_spec.rb +47 -17
- data/spec/edition_list_spec.rb +90 -4
- data/spec/emphasis_list_spec.rb +75 -11
- data/spec/emphasis_spec.rb +37 -21
- data/spec/examination_list_spec.rb +146 -20
- data/spec/extra_spec.rb +61 -22
- data/spec/extras_list_spec.rb +80 -17
- data/spec/frontmatter_spec.rb +141 -6
- data/spec/hash_spec.rb +49 -0
- data/spec/occupation_data_spec.rb +31 -13
- data/spec/occupation_list_spec.rb +88 -15
- data/spec/occupation_spec.rb +72 -28
- data/spec/pathway_spec.rb +47 -27
- data/spec/program_area_list_spec.rb +78 -4
- data/spec/program_area_spec.rb +70 -22
- data/spec/standard_spec.rb +94 -36
- data/spec/standards_list_spec.rb +130 -36
- data/spec/task_list_spec.rb +160 -51
- data/spec/task_spec.rb +120 -33
- data/verso.gemspec +3 -1
- metadata +41 -17
- data/lib/verso/http_get.rb +0 -9
- data/lib/verso/sol_correlation_list.rb +0 -53
- data/spec/sol_correlation_list_spec.rb +0 -74
data/lib/verso/extra.rb
CHANGED
@@ -1,38 +1,40 @@
|
|
1
1
|
module Verso
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
2
|
+
# Extra resource
|
3
|
+
#
|
4
|
+
# An extra (or related material) associated with a Course framework in
|
5
|
+
# Verso.
|
6
|
+
#
|
7
|
+
# @see http://api.cteresource.org/docs/courses/course/extras/extra
|
8
|
+
#
|
9
|
+
# @!attribute [r] code
|
10
|
+
# @return [String] Course code
|
11
|
+
# @!attribute [r] edition
|
12
|
+
# @return [String] Edition year
|
13
|
+
# @!attribute [r] name
|
14
|
+
# @return [String] Extra name, used as an identifier and not to
|
15
|
+
# be confused with its title, found by {Verso::ExtrasList}
|
16
|
+
# @!attribute [r] description
|
17
|
+
# @return [String] HTML-formatted Extra description
|
18
|
+
# @!attribute [r] title
|
19
|
+
# @return [String] Extra title
|
20
|
+
#
|
21
|
+
# @overload initialize(attrs={})
|
22
|
+
# @note Certain attributes are required for instantiation.
|
23
|
+
# @option attrs [String] :code Course code *Required*
|
24
|
+
# @option attrs [String] :edition Edition year *Required*
|
25
|
+
# @option attrs [String] :name Extra name *Required*
|
26
|
+
class Extra < Verso::Base
|
27
|
+
include HTTPGettable
|
28
|
+
attr_reader :code, :description, :edition, :name, :title
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def path
|
33
|
+
"/courses/#{code},#{edition}/extras/#{name}"
|
25
34
|
end
|
26
35
|
|
27
|
-
def
|
28
|
-
|
29
|
-
@raw_extra.merge!(
|
30
|
-
JSON.parse(
|
31
|
-
http_get("/courses/#{code},#{edition}/extras/#{name}")
|
32
|
-
)["extra"]
|
33
|
-
)
|
34
|
-
end
|
35
|
-
@raw_extra["description"]
|
36
|
+
def fetch
|
37
|
+
super[:extra]
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
data/lib/verso/extras_list.rb
CHANGED
@@ -1,22 +1,38 @@
|
|
1
1
|
module Verso
|
2
|
-
|
3
|
-
|
2
|
+
# Extras List resource
|
3
|
+
#
|
4
|
+
# A collection of {Verso::Extra} associated with a {Course} framework.
|
5
|
+
#
|
6
|
+
# @see http://api.cteresource.org/docs/courses/course/extras
|
7
|
+
#
|
8
|
+
# @example Get extras for 2012 edition of course 6320
|
9
|
+
# extras = Verso::ExtrasList.new(:code => "6320", :edition => "2012")
|
10
|
+
#
|
11
|
+
# @!attribute [r] code
|
12
|
+
# @return [String] Course code
|
13
|
+
# @!attribute [r] edition
|
14
|
+
# @return [String] Edition year
|
15
|
+
#
|
16
|
+
# @overload initialize(attrs={})
|
17
|
+
# @note Certain attributes are required for instantiation.
|
18
|
+
# @option attrs [String] :code Course code *Required*
|
19
|
+
# @option attrs [String] :edition Edition year *Required*
|
20
|
+
class ExtrasList < Verso::Base
|
4
21
|
include Enumerable
|
5
|
-
include
|
22
|
+
include HTTPGettable
|
23
|
+
extend Forwardable
|
24
|
+
attr_reader :code, :edition
|
25
|
+
def_delegators :extras, :[], :each, :empty?, :last, :length
|
6
26
|
|
7
|
-
|
8
|
-
@code, @edition = opts[:code], opts[:edition]
|
9
|
-
end
|
27
|
+
private
|
10
28
|
|
11
29
|
def extras
|
12
|
-
@extras ||=
|
13
|
-
|
14
|
-
)["extras"].
|
15
|
-
collect { |e| Extra.new(e.merge("code" => code, "edition" => edition)) }
|
30
|
+
@extras ||= get_attr(:extras).
|
31
|
+
collect { |e| Extra.new(e.merge(:code => code, :edition => edition)) }
|
16
32
|
end
|
17
33
|
|
18
|
-
def
|
19
|
-
extras
|
34
|
+
def path
|
35
|
+
"/courses/#{code},#{edition}/extras/"
|
20
36
|
end
|
21
37
|
end
|
22
38
|
end
|
data/lib/verso/frontmatter.rb
CHANGED
@@ -1,18 +1,50 @@
|
|
1
1
|
module Verso
|
2
|
-
|
3
|
-
|
2
|
+
# Frontmatter resource
|
3
|
+
#
|
4
|
+
# Frontmatter for {Verso::Course} framework.
|
5
|
+
#
|
6
|
+
# @see http://api.cteresource.org/docs/courses/course/frontmatter
|
7
|
+
#
|
8
|
+
# @!attribute [r] acknowledgments_text
|
9
|
+
# @return [String] HTML-formatted acknowledgments
|
10
|
+
# @!attribute [r] attribution_block
|
11
|
+
# @return [String] HTML-formatted attribution
|
12
|
+
# @!attribute [r] code
|
13
|
+
# @return [String] Course code
|
14
|
+
# @!attribute [r] copyright_year
|
15
|
+
# @return [String] Copyright year
|
16
|
+
# @!attribute [r] developed_by
|
17
|
+
# @return [String] HTML-formatted developed-by text
|
18
|
+
# @!attribute [r] developed_for
|
19
|
+
# @return [String] HTML-formatted developed-for text
|
20
|
+
# @!attribute [r] edition
|
21
|
+
# @return [String] Edition year
|
22
|
+
# @!attribute [r] foreword_text
|
23
|
+
# @return [String] HTML-formatted foreword
|
24
|
+
# @!attribute [r] introduction_text
|
25
|
+
# @return [String] HTML-formatted introduction_text
|
26
|
+
# @!attribute [r] notice_block
|
27
|
+
# @return [String] HTML formatted notice_block
|
28
|
+
#
|
29
|
+
# @overload initialize(attrs={})
|
30
|
+
# @note Any attributes may be set upon instantiation, using Options Hash.
|
31
|
+
# The following are required:
|
32
|
+
# @option attrs [String] :code Course code *Required*
|
33
|
+
# @option attrs [String] :edition Edition year *Required*
|
34
|
+
class Frontmatter < Verso::Base
|
35
|
+
include HTTPGettable
|
36
|
+
attr_reader :acknowledgments_text, :attribution_block, :code,
|
37
|
+
:copyright_year, :developed_by, :developed_for, :edition,
|
38
|
+
:foreword_text, :introduction_text, :notice_block
|
4
39
|
|
5
|
-
|
6
|
-
|
40
|
+
private
|
41
|
+
|
42
|
+
def fetch
|
43
|
+
super[:frontmatter]
|
7
44
|
end
|
8
45
|
|
9
|
-
def
|
10
|
-
|
11
|
-
@raw_frontmatter = JSON.parse(
|
12
|
-
http_get("/courses/#{@raw_frontmatter['code']},#{@raw_frontmatter['edition']}/frontmatter")
|
13
|
-
)["frontmatter"]
|
14
|
-
end
|
15
|
-
@raw_frontmatter[mname.to_s]
|
46
|
+
def path
|
47
|
+
"/courses/#{code},#{edition}/frontmatter"
|
16
48
|
end
|
17
49
|
end
|
18
50
|
end
|
data/lib/verso/hash.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class Hash
|
2
|
+
def symbolize_nested_keys!
|
3
|
+
keys.each do |key|
|
4
|
+
self[(key.to_sym rescue key) || key] = if self[key].is_a?(Hash)
|
5
|
+
delete(key).symbolize_nested_keys!
|
6
|
+
elsif self[key].is_a?(Array)
|
7
|
+
delete(key).collect do |i|
|
8
|
+
if i.is_a?(Hash)
|
9
|
+
i.symbolize_nested_keys!
|
10
|
+
end
|
11
|
+
i
|
12
|
+
end
|
13
|
+
else
|
14
|
+
delete(key)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
self
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Verso
|
2
|
+
# Mixin for classes derived from {Verso::Base}. Provides the capability to
|
3
|
+
# fetch the JSON resource to update attributes of the class.
|
4
|
+
#
|
5
|
+
# @abstract Implement a path method that gives the relative path of the
|
6
|
+
# corresponding JSON resource.
|
7
|
+
module HTTPGettable
|
8
|
+
protected
|
9
|
+
|
10
|
+
# Get an attribute from the attributes store {#attrs}. Fetch and merge
|
11
|
+
# first if the attribute store doesn't have the key.
|
12
|
+
#
|
13
|
+
# @param [Symbol] attr The attribute key
|
14
|
+
# @return [Object] The attribute
|
15
|
+
def get_attr(attr)
|
16
|
+
attrs.merge!(fetch) unless attrs.has_key?(attr)
|
17
|
+
super attr
|
18
|
+
end
|
19
|
+
|
20
|
+
# HTTP GET the JSON resource
|
21
|
+
# @return [String] JSON resource
|
22
|
+
def http_get
|
23
|
+
Net::HTTP.get('api.cteresource.org', path, 80)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Hash] Resource hash
|
27
|
+
def fetch
|
28
|
+
JSON.parse(http_get).symbolize_nested_keys!
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/verso/occupation.rb
CHANGED
@@ -1,25 +1,47 @@
|
|
1
1
|
module Verso
|
2
|
-
|
3
|
-
|
2
|
+
# Occupation resource
|
3
|
+
#
|
4
|
+
# An occupation is contained by a Pathway
|
5
|
+
#
|
6
|
+
# @see http://api.cteresource.org/docs/occupations/occupation
|
7
|
+
# @see http://www.careertech.org/career-clusters/clusters-occupations.html
|
8
|
+
#
|
9
|
+
# @!attribute [r] description
|
10
|
+
# @return [String] HTML-formatted Occupation description
|
11
|
+
# @!attribute [r] id
|
12
|
+
# @return [Fixnum] Occupation ID
|
13
|
+
# @!attribute [r] preparations
|
14
|
+
# @return [Array] Collection of preparation titles (strings)
|
15
|
+
# @!attribute [r] title
|
16
|
+
# @return [String] Occupation title
|
17
|
+
#
|
18
|
+
# @overload initialize(attrs={})
|
19
|
+
# @note Any attributes may be set upon instantiation, using Options Hash.
|
20
|
+
# The following are required:
|
21
|
+
# @option attrs [Fixnum] :id Occupation ID *Required*
|
22
|
+
class Occupation < Verso::Base
|
23
|
+
include HTTPGettable
|
24
|
+
attr_reader :description, :id, :preparations, :title
|
4
25
|
|
5
|
-
|
6
|
-
|
26
|
+
# @return [Verso::Pathway] Pathway that is the parent of this occupation
|
27
|
+
def pathway
|
28
|
+
@pathway ||= Pathway.new(get_attr(:pathway))
|
7
29
|
end
|
8
30
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@raw_occupation[mname.to_s]
|
31
|
+
# @return [Array] Collection of related {Verso::Course} objects
|
32
|
+
def related_courses
|
33
|
+
@related_courses ||= get_attr(:related_courses).
|
34
|
+
collect { |c| Course.new(c) }
|
14
35
|
end
|
15
36
|
|
16
|
-
|
17
|
-
|
18
|
-
|
37
|
+
private
|
38
|
+
|
39
|
+
def fetch
|
40
|
+
super[:occupation]
|
19
41
|
end
|
20
42
|
|
21
|
-
def
|
22
|
-
|
43
|
+
def path
|
44
|
+
"/occupations/#{id}"
|
23
45
|
end
|
24
46
|
end
|
25
47
|
end
|
@@ -1,30 +1,51 @@
|
|
1
1
|
module Verso
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
# Occupation Data
|
3
|
+
#
|
4
|
+
# A list of occupations grouped by the Cluster/Pathway that contains them.
|
5
|
+
# Occupation Data is not an independent resource. It is a component of
|
6
|
+
# {Verso::OccupationList}, {Verso::Course}, and {Verso::Emphasis}.
|
7
|
+
#
|
8
|
+
# @see http://api.cteresource.org/docs/academics/emphasis
|
9
|
+
# @see http://api.cteresource.org/docs/courses/course
|
10
|
+
# @see http://api.cteresource.org/docs/occupations
|
11
|
+
#
|
12
|
+
# @note Because an OccupationData object is created for you by other
|
13
|
+
# resources you should never need to instantiate one yourself.
|
14
|
+
class OccupationData < Verso::Base
|
15
|
+
# @return [Verso::Cluster] Cluster (grandparent of occupations)
|
7
16
|
def cluster
|
8
|
-
@cluster ||= Cluster.new(
|
17
|
+
@cluster ||= Cluster.new(get_attr(:cluster))
|
9
18
|
end
|
10
19
|
|
11
|
-
|
12
|
-
|
20
|
+
# @return [Array] Collection of {Verso::Occupation} objects
|
21
|
+
def occupations
|
22
|
+
@occupations ||= get_attr(:occupations).collect { |o| Occupation.new(o) }
|
13
23
|
end
|
14
24
|
|
15
|
-
|
16
|
-
|
17
|
-
|
25
|
+
# @return [Verso::Pathway] Pathway (parent of occupations)
|
26
|
+
def pathway
|
27
|
+
@pathway ||= Pathway.new(get_attr(:pathway))
|
18
28
|
end
|
19
29
|
|
30
|
+
# Find OccupationData by cluster, pathway, and occupation slugs
|
31
|
+
#
|
32
|
+
# @example Find an OccupationData for an occupation
|
33
|
+
# od = Verso::OccupationData.find_by_slugs('finance', 'accounting', 'cost-analyst')
|
34
|
+
# od.occupations.count # => 1
|
35
|
+
# od.occupations.first.title # => 'Cost Analyst'
|
36
|
+
#
|
37
|
+
# @param [String] cslug Cluster slug
|
38
|
+
# @param [String] pslug Pathway slug
|
39
|
+
# @param [String] slug Occupation slug
|
40
|
+
# @return [Verso::OccupationData,nil] Containing only one Occupation
|
20
41
|
def self.find_by_slugs(cslug, pslug, slug)
|
21
42
|
cluster = ClusterList.new.find { |c| c.title.parameterize == cslug }
|
22
43
|
pathway = cluster.pathways.find { |p| p.title.parameterize == pslug }
|
23
44
|
occupation = pathway.occupations.find { |o| o.title.parameterize == slug }
|
24
45
|
OccupationData.new(
|
25
|
-
{
|
26
|
-
|
27
|
-
|
46
|
+
{ :cluster => { :title => cluster.title },
|
47
|
+
:pathway => { :title => pathway.title },
|
48
|
+
:occupations => [{ :title => occupation.title }] }
|
28
49
|
)
|
29
50
|
end
|
30
51
|
end
|
@@ -1,32 +1,35 @@
|
|
1
1
|
module Verso
|
2
|
-
|
2
|
+
# Occupation list resource
|
3
|
+
#
|
4
|
+
# Search {Verso::Occupation} objects using free text. Result is a collection
|
5
|
+
# of {Verso::OccupationData} objects containing relevant {Verso::Occupation}
|
6
|
+
# objects.
|
7
|
+
#
|
8
|
+
# @see http://api.cteresource.org/docs/occupations
|
9
|
+
#
|
10
|
+
# @example Search by free text
|
11
|
+
# ods = Verso::OccupationList.new(:text => "golf") # => golf-related ODs
|
12
|
+
#
|
13
|
+
# @overload initialize(attrs={})
|
14
|
+
# @option attrs [String] :text Free text
|
15
|
+
class OccupationList < Verso::Base
|
3
16
|
include Enumerable
|
4
|
-
include
|
17
|
+
include HTTPGettable
|
18
|
+
extend Forwardable
|
19
|
+
def_delegators :occupations, :[], :each, :empty?, :last, :length
|
5
20
|
|
6
|
-
|
7
|
-
@q_uri = Addressable::URI.new(
|
8
|
-
:path => '/occupations',
|
9
|
-
:query_values => raw_query
|
10
|
-
)
|
11
|
-
end
|
21
|
+
private
|
12
22
|
|
13
23
|
def occupations
|
14
|
-
|
15
|
-
|
24
|
+
return [] if attrs[:text].to_s.empty?
|
25
|
+
@occupations ||= get_attr(:occupation_data).
|
16
26
|
collect { |o| OccupationData.new(o) }.
|
17
27
|
sort_by { |o| [o.cluster.title, o.pathway.title] }
|
18
28
|
end
|
19
29
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
def last
|
25
|
-
occupations[-1]
|
26
|
-
end
|
27
|
-
|
28
|
-
def empty?
|
29
|
-
occupations.empty?
|
30
|
+
def path
|
31
|
+
@path ||= Addressable::URI.new(:path => '/occupations',
|
32
|
+
:query_values => attrs).request_uri
|
30
33
|
end
|
31
34
|
end
|
32
35
|
end
|
data/lib/verso/pathway.rb
CHANGED
@@ -1,25 +1,43 @@
|
|
1
1
|
module Verso
|
2
|
-
|
3
|
-
|
2
|
+
# Pathway Resource
|
3
|
+
#
|
4
|
+
# @see http://api.cteresource.org/docs/pathways/pathway
|
5
|
+
# @see http://www.careertech.org/career-clusters/clusters-occupations.html
|
6
|
+
#
|
7
|
+
# @!attribute [r] description
|
8
|
+
# @return [String] HTML-formatted Pathway description
|
9
|
+
# @!attribute [r] id
|
10
|
+
# @return [Fixnum] Pathway id
|
11
|
+
# @!attribute [r] title
|
12
|
+
# @return [String] Pathway title
|
13
|
+
#
|
14
|
+
# @overload initialize(attrs={})
|
15
|
+
# @note Any attributes may be set upon instantiation, using Options Hash.
|
16
|
+
# The following are required:
|
17
|
+
# @option attrs [Fixnum] :id Pathway id *Required*
|
18
|
+
class Pathway < Verso::Base
|
19
|
+
include HTTPGettable
|
20
|
+
attr_reader :description, :id, :title
|
4
21
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
def method_missing(mname)
|
10
|
-
if @raw_pathway[mname.to_s].nil?
|
11
|
-
@raw_pathway = JSON.parse(http_get("/pathways/#{id}"))["pathway"]
|
12
|
-
end
|
13
|
-
@raw_pathway[mname.to_s]
|
22
|
+
# @return [Verso::Cluster] Parent Cluster
|
23
|
+
def cluster
|
24
|
+
@cluster ||= Cluster.new(get_attr(:cluster))
|
14
25
|
end
|
15
26
|
|
27
|
+
# @return [Array] Children {Verso::Occupation} objects
|
16
28
|
def occupations
|
17
|
-
@occupations ||=
|
29
|
+
@occupations ||= get_attr(:occupations).
|
18
30
|
collect { |o| Occupation.new(o) }
|
19
31
|
end
|
20
32
|
|
21
|
-
|
22
|
-
|
33
|
+
private
|
34
|
+
|
35
|
+
def fetch
|
36
|
+
super[:pathway]
|
37
|
+
end
|
38
|
+
|
39
|
+
def path
|
40
|
+
"/pathways/#{id}"
|
23
41
|
end
|
24
42
|
end
|
25
43
|
end
|