verso 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.
Files changed (63) hide show
  1. data/.gitignore +2 -0
  2. data/README.md +10 -22
  3. data/lib/verso.rb +10 -2
  4. data/lib/verso/base.rb +50 -0
  5. data/lib/verso/cluster.rb +55 -25
  6. data/lib/verso/cluster_list.rb +15 -10
  7. data/lib/verso/correlation_list.rb +30 -40
  8. data/lib/verso/course.rb +106 -43
  9. data/lib/verso/course_list.rb +57 -21
  10. data/lib/verso/credential.rb +94 -20
  11. data/lib/verso/credential_list.rb +30 -15
  12. data/lib/verso/duty_area.rb +23 -10
  13. data/lib/verso/edition_list.rb +18 -10
  14. data/lib/verso/emphasis.rb +26 -12
  15. data/lib/verso/emphasis_list.rb +18 -10
  16. data/lib/verso/examination_list.rb +28 -12
  17. data/lib/verso/extra.rb +34 -32
  18. data/lib/verso/extras_list.rb +28 -12
  19. data/lib/verso/frontmatter.rb +43 -11
  20. data/lib/verso/hash.rb +19 -0
  21. data/lib/verso/http_gettable.rb +31 -0
  22. data/lib/verso/occupation.rb +36 -14
  23. data/lib/verso/occupation_data.rb +35 -14
  24. data/lib/verso/occupation_list.rb +23 -20
  25. data/lib/verso/pathway.rb +32 -14
  26. data/lib/verso/program_area.rb +42 -21
  27. data/lib/verso/program_area_list.rb +15 -11
  28. data/lib/verso/standard.rb +45 -23
  29. data/lib/verso/standards_list.rb +41 -30
  30. data/lib/verso/task.rb +52 -17
  31. data/lib/verso/task_list.rb +40 -17
  32. data/lib/verso/version.rb +1 -1
  33. data/spec/cluster_list_spec.rb +78 -5
  34. data/spec/cluster_spec.rb +106 -9
  35. data/spec/correlation_list_spec.rb +108 -50
  36. data/spec/course_list_spec.rb +112 -23
  37. data/spec/course_spec.rb +321 -127
  38. data/spec/credential_list_spec.rb +83 -52
  39. data/spec/credential_spec.rb +358 -19
  40. data/spec/duty_area_spec.rb +47 -17
  41. data/spec/edition_list_spec.rb +90 -4
  42. data/spec/emphasis_list_spec.rb +75 -11
  43. data/spec/emphasis_spec.rb +37 -21
  44. data/spec/examination_list_spec.rb +146 -20
  45. data/spec/extra_spec.rb +61 -22
  46. data/spec/extras_list_spec.rb +80 -17
  47. data/spec/frontmatter_spec.rb +141 -6
  48. data/spec/hash_spec.rb +49 -0
  49. data/spec/occupation_data_spec.rb +31 -13
  50. data/spec/occupation_list_spec.rb +88 -15
  51. data/spec/occupation_spec.rb +72 -28
  52. data/spec/pathway_spec.rb +47 -27
  53. data/spec/program_area_list_spec.rb +78 -4
  54. data/spec/program_area_spec.rb +70 -22
  55. data/spec/standard_spec.rb +94 -36
  56. data/spec/standards_list_spec.rb +130 -36
  57. data/spec/task_list_spec.rb +160 -51
  58. data/spec/task_spec.rb +120 -33
  59. data/verso.gemspec +3 -1
  60. metadata +41 -17
  61. data/lib/verso/http_get.rb +0 -9
  62. data/lib/verso/sol_correlation_list.rb +0 -53
  63. data/spec/sol_correlation_list_spec.rb +0 -74
@@ -1,36 +1,72 @@
1
1
  module Verso
2
- class CourseList
2
+ # Search Verso courses by :text, :cluster, :program_area, :code, :edition,
3
+ # or any combination and get back an Array-like collection of
4
+ # {Verso::Course} objects.
5
+ #
6
+ # @see http://api.cteresource.org/docs/courses
7
+ #
8
+ # @example Search by text
9
+ # courses = Verso::CourseList.new(:text => "golf") # => <Verso::CourseList:0x007fa5a10bbb68 @attrs={:text=>"golf"}>
10
+ # courses.first.title # => "Turf Grass Applications, Advanced"
11
+ #
12
+ # @example Search by cluster
13
+ # course = Verso::CourseList.new(:cluster => "Information Technology).first
14
+ # course.title # => "Computer Applications"
15
+ #
16
+ # @example Search by program area
17
+ # course = Verso::CourseList.new(:program_area => "Career Connections").last
18
+ # course.title # => "Career Investigation Phase I"
19
+ #
20
+ # @example Search by code
21
+ # courses = Verso::CourseList.new(:code => "6320") # => <Verso::CourseList:0x007fa5a1f27a08 @attrs={:code=>"6320"}>
22
+ # courses.first # => <Verso::Course:0x007fa5a1f3e5c8 @attrs={:duration=>36, :edition=>"2012", :code=>"6320" . . . }>
23
+ # courses.first.code # => "6320"
24
+ #
25
+ # @example Search by edition
26
+ # all_2012 = Verso::CourseList.new(:edition => "2012")
27
+ #
28
+ # @example Search by combination
29
+ # courses = Verso::CourseList.new(:text => "internet", :cluster => "Marketing") # => <Verso::CourseList:0x007fa5a19b6c90 @attrs={ . . . }>
30
+ # courses.count # => 1
31
+ #
32
+ # @example An empty search returns an empty list
33
+ # courses = Verso::CourseList.new
34
+ # courses.count # => 0
35
+ #
36
+ # @overload initialize(attrs={})
37
+ # @option attrs [String] :code Course code
38
+ # @option attrs [String] :edition Edition year
39
+ # @option attrs [String] :text Free text
40
+ # @option attrs [String] :cluster Cluster title
41
+ # @option attrs [String] :program_area Program Area title
42
+ class CourseList < Verso::Base
3
43
  include Enumerable
4
- include HTTPGet
44
+ include HTTPGettable
45
+ extend Forwardable
46
+ def_delegators :courses, :[], :each, :empty?, :last, :length
5
47
 
6
- def initialize(raw_query)
7
- @q_uri = Addressable::URI.new(
8
- :path => '/courses',
9
- :query_values => raw_query.
10
- select { |k, v| v }.
11
- reject { |k, v| v.to_s.empty? }
12
- )
13
- end
48
+ private
14
49
 
15
50
  def courses
16
- @courses ||= if @q_uri.query_values.values.any?
17
- JSON.parse(http_get(@q_uri.request_uri))["courses"].
18
- collect { |c| Course.new(c) }
51
+ @courses ||= if q_uri.query_values.values.any?
52
+ get_attr(:courses).collect { |c| Course.new(c) }
19
53
  else
20
54
  []
21
55
  end
22
56
  end
23
57
 
24
- def each &block
25
- courses.each &block
26
- end
27
-
28
- def last
29
- courses[-1]
58
+ def q_uri
59
+ Addressable::URI.new(
60
+ :path => '/courses',
61
+ :query_values => attrs.
62
+ reject { |k, v| k == :courses }.
63
+ select { |k, v| v }.
64
+ reject { |k, v| v.to_s.empty? }
65
+ )
30
66
  end
31
67
 
32
- def empty?
33
- courses.empty?
68
+ def path
69
+ q_uri.request_uri
34
70
  end
35
71
  end
36
72
  end
@@ -1,34 +1,108 @@
1
1
  module Verso
2
- class Credential
3
- include HTTPGet
2
+ # Credential Resource
3
+ #
4
+ # The usual way to get a Credential would be to use {Verso::CredentialList}
5
+ # or to get one from a related object, such as a {Verso::Course} object.
6
+ #
7
+ # @see http://api.cteresource.org/docs/credentials/credential
8
+ #
9
+ # @!attribute [r] admin_notes
10
+ # @return [String] HTML-formatted test administration notes
11
+ # @!attribute [r] amt_seal
12
+ # @return [Booelean] Advanced Math and Technology seal
13
+ # @!attribute [r] contact_info
14
+ # @return [String] Contractor contact information
15
+ # @!attribute [r] cost
16
+ # @return [String] Cost
17
+ # @!attribute [r] cte_seal
18
+ # @return [Boolean] CTE seal
19
+ # @!attribute [r] description
20
+ # @return [String] HTML-formatted text describing the credential.
21
+ # @!attribute [r] has_ancestor
22
+ # @return [Boolean] Did this credential exist in an earlier edition?
23
+ # @!attribute [r] how_to_earn_it
24
+ # @return [String] HTML-formatted text about how to earn it.
25
+ # @!attribute [r] id
26
+ # @return [Fixnum] Credential id
27
+ # @!attribute [r] items
28
+ # @return [String] Number of test items
29
+ # @!attribute [r] passing_score
30
+ # @return [Sring] Passing score
31
+ # @!attribute [r] pretest
32
+ # @return [Boolean,nil] Is a pre-test, study guide, or blueprint available?
33
+ # @!attribute [r] proctor
34
+ # @return [String] Test examiner/proctor
35
+ # @!attribute [r] program_area
36
+ # @return [String] Title of associated program area
37
+ # @!attribute [r] retired
38
+ # @return [Boolean] Is this credential slated for deletion?
39
+ # @!attribute [r] site
40
+ # @return [String] Allowed testing site
41
+ # @!attribute [r] time
42
+ # @return [String] Time allowed
43
+ # @!attribute [r] title
44
+ # @return [String] Credential title
45
+ # @!attribute [r] type
46
+ # @return ['Certification','License'] Credential type
47
+ # @!attribute [r] verified_credit
48
+ # @return [Boolean] Verified credit
49
+ #
50
+ # @overload initialize(attrs={})
51
+ # @note Any attributes may be set upon instantiation, using Options Hash.
52
+ # The following are required:
53
+ # @option attrs [Fixnum] :id Credential id *Required*
54
+ class Credential < Verso::Base
55
+ include HTTPGettable
56
+ attr_reader :admin_notes, :amt_seal, :contact_info, :cost, :cte_seal,
57
+ :description, :has_ancestor, :how_to_earn_it, :id, :items, :passing_score,
58
+ :pretest, :proctor, :program_area, :retired, :site, :time, :title, :type,
59
+ :verified_credit
60
+ alias amt_seal? amt_seal
61
+ alias cte_seal? cte_seal
62
+ alias has_ancestor? has_ancestor
63
+ alias retired? retired
64
+ alias verified_credit? verified_credit
4
65
 
5
- def initialize(opts)
6
- @raw_credential = opts
66
+ # VDOE contacts, each responding to #name, #email, and #phone, all Strings.
67
+ #
68
+ # @return [Array] VDOE contacts
69
+ def contacts
70
+ @contacts ||= get_attr(:contacts).collect { |c| OpenStruct.new(c) }
7
71
  end
8
72
 
9
- def method_missing(mname)
10
- if @raw_credential[mname.to_s].nil?
11
- @raw_credential.merge!(
12
- JSON.parse(http_get("/credentials/#{id}"))["credential"]
13
- )
14
- end
15
- @raw_credential[mname.to_s]
73
+ # @return [String] Contractor name
74
+ def contractor_name
75
+ get_attr(:contractor_name).to_s
16
76
  end
17
77
 
18
- def source
19
- @source ||= OpenStruct.new(method_missing(:source))
78
+ # @return [String] Details
79
+ def details
80
+ get_attr(:details).to_s # #to_s b/c API sometimes returns nil
20
81
  end
21
82
 
22
- def details
23
- @details ||= if @raw_credential.has_key?("details")
24
- @raw_credential["details"]
25
- else
26
- method_missing(:details)
27
- end.to_s
83
+ # Source. Responds to #title, #url, and #contact_info. All are Strings or
84
+ # nil. The last is HTML-formatted.
85
+ #
86
+ # @return [OpenStruct] Source
87
+ def source
88
+ # force update if we only have part of source
89
+ attrs.merge!(fetch) unless attrs[:source] && attrs[:source].has_key?(:url)
90
+ OpenStruct.new(get_attr(:source))
28
91
  end
29
92
 
93
+ # @return [Array] Collection of related {Verso::Course} objects
30
94
  def related_courses
31
- method_missing(:related_courses).collect { |rc| Course.new(rc) }
95
+ @courses ||= get_attr(:related_courses).collect { |rc| Course.new(rc) }
96
+ end
97
+
98
+ private
99
+
100
+ def path
101
+ "/credentials/#{id}"
102
+ end
103
+
104
+ def fetch
105
+ super[:credential]
32
106
  end
33
107
  end
34
108
  end
@@ -1,28 +1,43 @@
1
1
  module Verso
2
- class CredentialList
2
+ # Credential list resource
3
+ #
4
+ # Search for {Verso::Credential} objects using free text, or get back the
5
+ # list of all of them.
6
+ #
7
+ # @see http://api.cteresource.org/docs/credentials
8
+ #
9
+ # @example All
10
+ # creds = Verso::CredentialList.new # => everything
11
+ # creds.first # => <Verso::Credential:0x007fb1a39e4038 . . . >
12
+ #
13
+ # @example Search
14
+ # creds = Verso::CredentialList.new(:text => "nocti")
15
+ # creds.first.source.title # => "National Occupational Competency Testing Institute (NOCTI)"
16
+ #
17
+ # @overload initialize(attrs={})
18
+ # @option attrs [String] :text Free text
19
+ class CredentialList < Verso::Base
3
20
  include Enumerable
4
- include HTTPGet
21
+ include HTTPGettable
22
+ extend Forwardable
23
+ def_delegators :credentials, :[], :each, :empty?, :last, :length
5
24
 
6
- attr_reader :credentials
25
+ private
7
26
 
8
- def initialize(opts={})
9
- @q_uri = Addressable::URI.new(:path => '/credentials')
10
- @q_uri.query_values = opts unless opts[:text].to_s.empty?
11
- @credentials = JSON.parse(http_get(@q_uri.request_uri))["credentials"].
27
+ def credentials
28
+ @credentials ||= get_attr(:credentials).
12
29
  collect { |c| Credential.new(c) }.
13
30
  sort_by { |c| c.title }
14
31
  end
15
32
 
16
- def each &block
17
- credentials.each &block
33
+ def path
34
+ q_uri ||= Addressable::URI.new(:path => '/credentials')
35
+ q_uri.query_values = { :text => text } unless text.empty?
36
+ q_uri.request_uri
18
37
  end
19
38
 
20
- def last
21
- credentials[-1]
22
- end
23
-
24
- def empty?
25
- credentials.empty?
39
+ def text
40
+ attrs[:text] ? attrs[:text] : ''
26
41
  end
27
42
  end
28
43
  end
@@ -1,16 +1,29 @@
1
1
  module Verso
2
- class DutyArea
3
- attr_reader :title, :context
4
-
5
- def initialize(raw_da, context)
6
- @context = context
7
- @title = raw_da["title"]
8
- @raw_tasks = raw_da["tasks"]
9
- end
2
+ # Duty Area
3
+ #
4
+ # A group of tasks in a {Verso::TaskList}.
5
+ #
6
+ # @see http://api.cteresource.org/docs/courses/course/tasks
7
+ #
8
+ # @!attribute [r] code
9
+ # @return [String] Course code
10
+ # @!attribute [r] edition
11
+ # @return [String] Course edition year
12
+ # @!attribute [r] title
13
+ # @return [String] Duty Area title
14
+ #
15
+ # @note A DutyArea is created for you by {Verso::TaskList}. It corresponds
16
+ # to a portion of the Task List resource. You should never need to
17
+ # instantiate one yourself.
18
+ class DutyArea < Verso::Base
19
+ attr_reader :code, :edition, :title
10
20
 
21
+ # Tasks within this Duty Area
22
+ #
23
+ # @return [Array] {Verso::Task} objects
11
24
  def tasks
12
- @tasks ||= @raw_tasks.collect do |t|
13
- Task.new(t.merge("code" => context.code, "edition" => context.edition))
25
+ @tasks ||= get_attr(:tasks).collect do |t|
26
+ Task.new(t.merge(:code => code, :edition => edition))
14
27
  end
15
28
  end
16
29
  end
@@ -1,19 +1,27 @@
1
1
  module Verso
2
- class EditionList
2
+ # Edition List resource
3
+ #
4
+ # A collection of Edition proxies that respond to #year, returning a string
5
+ # year like '2012'.
6
+ #
7
+ # @example Get a list
8
+ # editions = Verso::EditionList.new
9
+ # editions.first.year => # "2012"
10
+ #
11
+ class EditionList < Verso::Base
3
12
  include Enumerable
4
- include HTTPGet
13
+ include HTTPGettable
14
+ extend Forwardable
15
+ def_delegators :editions, :[], :each, :empty?, :last, :length
5
16
 
6
- def editions
7
- @editions ||= JSON.parse(http_get('/editions/'))["editions"].
8
- collect { |e| OpenStruct.new(e) }
9
- end
17
+ private
10
18
 
11
- def each &block
12
- editions.each &block
19
+ def editions
20
+ @editions ||= get_attr(:editions).collect { |e| OpenStruct.new(e) }
13
21
  end
14
22
 
15
- def last
16
- editions[-1]
23
+ def path
24
+ "/editions/"
17
25
  end
18
26
  end
19
27
  end
@@ -1,21 +1,35 @@
1
1
  module Verso
2
- class Emphasis
3
- include HTTPGet
2
+ # Academic Emphasis resource
3
+ #
4
+ # @see http://api.cteresource.org/docs/academics/emphasis
5
+ #
6
+ # @!attribute [r] id
7
+ # @return [Fixnum] Academic Emphasis id
8
+ # @!attribute [r] title
9
+ # @return Academic Emphasis title
10
+ #
11
+ # @overload initialize(attrs={})
12
+ # @note Any attributes may be set upon instantiation, using Options Hash.
13
+ # The following are required:
14
+ # @option attrs [Fixnum] :id Academic Emphasis id *Required*
15
+ class Emphasis < Verso::Base
16
+ include HTTPGettable
17
+ attr_reader :id, :title
4
18
 
5
- def initialize(raw_emphasis)
6
- @raw_emphasis = raw_emphasis
19
+ # @return [Array] Collection of related {Verso::OccupationData} objects
20
+ def occupation_data
21
+ @occupation_data ||= get_attr(:occupation_data).
22
+ collect { |od| OccupationData.new(od) }
7
23
  end
8
24
 
9
- def method_missing(mname)
10
- if !@raw_emphasis.has_key?(mname.to_s)
11
- @raw_emphasis = JSON.parse(http_get("/academics/#{id}"))["emphasis"]
12
- end
13
- @raw_emphasis[mname.to_s]
25
+ private
26
+
27
+ def fetch
28
+ super[:emphasis]
14
29
  end
15
30
 
16
- def occupation_data
17
- @occupation_data ||= method_missing(:occupation_data).
18
- collect { |od| OccupationData.new(od) }
31
+ def path
32
+ "/academics/#{id}"
19
33
  end
20
34
  end
21
35
  end
@@ -1,19 +1,27 @@
1
1
  module Verso
2
- class EmphasisList
2
+ # Academic Emphasis List resource
3
+ #
4
+ # A collection of all {Verso::Emphasis} objects.
5
+ #
6
+ # @see http://api.cteresource.org/docs/academics
7
+ #
8
+ # @example Get a list
9
+ # emphases = Verso::EmphasisList.new # => all of them
10
+ # emphases.first.title # => "Algebra"
11
+ class EmphasisList < Verso::Base
3
12
  include Enumerable
4
- include HTTPGet
13
+ include HTTPGettable
14
+ extend Forwardable
15
+ def_delegators :emphases, :[], :each, :empty?, :last, :length
5
16
 
6
- def emphases
7
- @emphases ||= JSON.parse(http_get('/academics/'))["emphases"].
8
- collect { |em| Emphasis.new(em) }
9
- end
17
+ private
10
18
 
11
- def each &block
12
- emphases.each &block
19
+ def emphases
20
+ @emphases ||= get_attr(:emphases).collect { |em| Emphasis.new(em) }
13
21
  end
14
22
 
15
- def last
16
- emphases[-1]
23
+ def path
24
+ "/academics/"
17
25
  end
18
26
  end
19
27
  end
@@ -1,21 +1,37 @@
1
1
  module Verso
2
- class ExaminationList
2
+ # Examination List resource
3
+ #
4
+ # A collection of Examination stand-in objects that respond to:
5
+ # * #amt_seal @return [Boolean] AMT Seal
6
+ # * #passing_score @return [String] Passing score
7
+ # * #retired @return [Boolean] Slated to be deleted?
8
+ # * #source @return [String] Title of exam source
9
+ # * #title @return [String] Exam title
10
+ # * #verified_credit @return [Booelean] Verified credit
11
+ #
12
+ # The attributes of the Examination stand-ins are similar to
13
+ # {Verso::Credential}.
14
+ #
15
+ # @example Get the list
16
+ # exams = Verso::ExaminationList.new # => everything
17
+ # exams.first.title # => "Advanced Placement Computer Science A"
18
+ #
19
+ # @see http://api.cteresource.org/docs/examinations
20
+ class ExaminationList < Verso::Base
3
21
  include Enumerable
4
- include HTTPGet
22
+ include HTTPGettable
23
+ extend Forwardable
24
+ def_delegators :examinations, :[], :each, :empty?, :last, :length
5
25
 
6
- attr_reader :examinations
26
+ private
7
27
 
8
- def initialize
9
- @examinations = JSON.parse(http_get("/examinations/"))["examinations"].
10
- collect { |e| OpenStruct.new(e) }
28
+ def examinations
29
+ @examinations ||= get_attr(:examinations).
30
+ collect { |e| OpenStruct.new(e) }
11
31
  end
12
32
 
13
- def each &block
14
- examinations.each &block
15
- end
16
-
17
- def last
18
- examinations[-1]
33
+ def path
34
+ "/examinations/"
19
35
  end
20
36
  end
21
37
  end