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,39 +1,60 @@
1
1
  module Verso
2
- class ProgramArea
3
- include HTTPGet
4
-
5
- def initialize(raw_category)
6
- @raw_program_area = raw_category
7
- end
8
-
9
- def method_missing(mname)
10
- if @raw_program_area[mname.to_s].nil?
11
- @raw_program_area.merge!(
12
- JSON.parse(http_get("/program_areas/"))["program_areas"].
13
- find { |c| c["title"] == @raw_program_area["title"] }
14
- )
15
- end
16
- @raw_program_area[mname.to_s]
17
- end
18
-
19
- def description
20
- ""
21
- end
2
+ # Program Area
3
+ #
4
+ # Contained by {Verso::ProgramAreaList} resource
5
+ #
6
+ # @see http://api.cteresource.org/docs/program_areas
7
+ #
8
+ # @!attribute [r] deprecated
9
+ # @return [Boolean] Is this Program Area deprecated?
10
+ # @!attribute [r] official
11
+ # @return [Boolean] Is this an official VDOE Program Area?
12
+ # @!attribute [r] section_overview
13
+ # @return [String] HTML-formatted text describing Program Area
14
+ # @!attribute [r] title
15
+ # @return [String] Program Area title
16
+ # @!attribute [r] version_date
17
+ # @return [String] Date of last update
18
+ #
19
+ # @overload initialize(attrs={})
20
+ # @note Any attributes may be set upon instantiation, using Options Hash.
21
+ # The following are required:
22
+ # @option attrs [String] :title Program Area title *Required*
23
+ class ProgramArea < Verso::Base
24
+ include HTTPGettable
25
+ attr_reader :deprecated, :official, :section_overview, :title, :version_date
22
26
 
27
+ # @return [Array] Collection of related {Verso::Course} objects
23
28
  def courses
24
29
  @courses ||= CourseList.new(:program_area => slug.gsub('-', ' ')).
25
30
  sort_by { |c| c.title + c.edition }.
26
31
  uniq { |c| c.code + c.edition }
27
32
  end
28
33
 
34
+ # @return [String] Empty string to make consistent interface
35
+ def description
36
+ ""
37
+ end
38
+
39
+ # @return [String] Parameterized title
29
40
  def slug
30
41
  # swiped from ActiveSupport::Inflector
31
- parameterized_string = @raw_program_area["title"].dup
42
+ parameterized_string = title.dup
32
43
  parameterized_string.gsub!(/[^a-z0-9\-_]+/i, '-')
33
44
  re_sep = Regexp.escape('-')
34
45
  parameterized_string.gsub!(/#{re_sep}{2,}/, '-')
35
46
  parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '')
36
47
  parameterized_string.downcase
37
48
  end
49
+
50
+ private
51
+
52
+ def path
53
+ "/program_areas/"
54
+ end
55
+
56
+ def fetch
57
+ super[:program_areas].find { |pa| pa[:title] == title }
58
+ end
38
59
  end
39
60
  end
@@ -1,20 +1,24 @@
1
1
  module Verso
2
- class ProgramAreaList
2
+ # Program Area List resource
3
+ #
4
+ # A collection of {Verso::ProgramArea} objects.
5
+ #
6
+ # @see http://api.cteresource.org/docs/program_areas
7
+ class ProgramAreaList < Verso::Base
3
8
  include Enumerable
4
- include HTTPGet
9
+ include HTTPGettable
10
+ extend Forwardable
11
+ def_delegators :program_areas, :[], :each, :empty?, :last, :length
5
12
 
6
- def program_areas
7
- @program_areas ||= JSON.parse(
8
- http_get('/program_areas/')
9
- )["program_areas"].collect { |pa| ProgramArea.new(pa) }
10
- end
13
+ private
11
14
 
12
- def each &block
13
- program_areas.each &block
15
+ def program_areas
16
+ @program_areas ||= get_attr(:program_areas).
17
+ collect { |pa| ProgramArea.new(pa) }
14
18
  end
15
19
 
16
- def last
17
- program_areas[-1]
20
+ def path
21
+ "/program_areas/"
18
22
  end
19
23
  end
20
24
  end
@@ -1,37 +1,59 @@
1
1
  module Verso
2
- class Standard
3
- include HTTPGet
2
+ # Standard resource
3
+ #
4
+ # A standard that has been associated with a {Verso::Course}.
5
+ #
6
+ # @see http://api.cteresource.org/docs/courses/course/standards/standard
7
+ #
8
+ # @!attribute [r] code
9
+ # @return [String] Course code
10
+ # @!attribute [r] edition
11
+ # @return [String] Course edition year
12
+ # @!attribute [r] name
13
+ # @return [String] Standard name used as an identifier
14
+ # @!attribute [r] title
15
+ # @return [String] Standard title
16
+ #
17
+ # @overload initialize(attrs={})
18
+ # @note Any attributes may be set upon instantiation, using Options Hash.
19
+ # The following are required:
20
+ # @option attrs [String] :code Course code *Required*
21
+ # @option attrs [String] :edition Edition year *Required*
22
+ # @option attrs [String] :name Standard name (identifier) *Required*
23
+ class Standard < Verso::Base
24
+ include HTTPGettable
25
+ attr_reader :code, :edition, :name, :title
4
26
 
5
- def initialize(raw_standard, context=nil)
6
- @raw_standard = raw_standard
7
- @context = context
27
+ # @return [String] description
28
+ def description
29
+ get_attr(:description).to_s # sometimes nil
8
30
  end
9
31
 
10
- def method_missing(mname)
11
- if !@raw_standard.has_key?(mname.to_s)
12
- @raw_standard.merge!(JSON.parse(
13
- http_get("/courses/#{code},#{edition}/standards/#{name}")
14
- )["standard"])
15
- end
16
- @raw_standard[mname.to_s]
32
+ # @return [Array] collection of goals with #title, #description strings
33
+ def goals
34
+ @goals ||= get_attr(:goals).
35
+ collect { |raw_standard| OpenStruct.new(raw_standard) }
17
36
  end
18
37
 
19
- def code
20
- @context && @context.code
21
- end
22
38
 
23
- def edition
24
- @context && @context.edition
39
+ # @return [Array] collection of contained {Verso::Standard} objects
40
+ def sections
41
+ @sections ||= get_attr(:sections).
42
+ collect do |raw_section|
43
+ Standard.new(
44
+ raw_section.merge(:code => code, :edition => edition, :name => name)
45
+ )
46
+ end
25
47
  end
26
48
 
27
- def sections
28
- @sections ||= method_missing(:sections).
29
- collect { |raw_section| Standard.new(raw_section, @context) }
49
+ private
50
+
51
+ def fetch
52
+ super[:standard]
30
53
  end
31
54
 
32
- def goals
33
- @goals ||= method_missing(:goals).
34
- collect { |raw_standard| OpenStruct.new(raw_standard) }
55
+ def path
56
+ "/courses/#{code},#{edition}/standards/#{name}"
35
57
  end
36
58
  end
37
59
  end
@@ -1,49 +1,60 @@
1
1
  module Verso
2
- class StandardsList
2
+ # Standards List resource
3
+ #
4
+ # A collection of {Verso::Standard} objects correlated to a {Verso::Course}.
5
+ #
6
+ # @see http://api.cteresource.org/docs/courses/course/standards
7
+ #
8
+ # @!attribute [r] code
9
+ # @return [String] Course code
10
+ # @!attribute [r] edition
11
+ # @return [String] Course edition year
12
+ #
13
+ # @overload initialize(attrs={})
14
+ # @note Attributes required:
15
+ # @option attrs [String] :code Course code *Required*
16
+ # @option attrs [String] :edition Edition year *Required*
17
+ class StandardsList < Verso::Base
3
18
  include Enumerable
19
+ include HTTPGettable
20
+ extend Forwardable
21
+ def_delegators :standards, :[], :each, :empty?, :last, :length
22
+ attr_reader :code, :edition
4
23
 
5
- def initialize(raw, context=nil)
6
- @raw_standards = raw.is_a?(Array) ? raw : raw.values
7
- @context = context
8
- end
9
-
10
- def self.from_course(course)
11
- raw_standards = JSON.parse(
12
- Net::HTTP.get('api.cteresource.org',
13
- "/courses/#{course.code},#{course.edition}/standards/",
14
- 80)
15
- )["standards"]
16
- StandardsList.new(raw_standards, course)
17
- end
18
-
19
- def standards
20
- @standards ||= @raw_standards.
21
- sort_by { |s| s["title"] }.
22
- collect { |raw_standard| Standard.new(raw_standard, @context) }
24
+ # @return [Array] Non-SOL standards in this list
25
+ def non_sols
26
+ @non_sols ||= reject { |s| sol_titles.include?(s.title) }
23
27
  end
24
28
 
25
- def each &block
26
- standards.each &block
29
+ # @return [Array] SOL standards in this list
30
+ def sols
31
+ @sols ||= select { |s| sol_titles.include?(s.title) }
27
32
  end
28
33
 
29
- def last
30
- standards[-1]
34
+ # Find Standards by {Verso::Course}.
35
+ #
36
+ # @param course [Verso::Course] A {Verso::Course}
37
+ # @return [Verso::StandardsList] A {Verso::Course}'s standards
38
+ def self.from_course(course)
39
+ StandardsList.new(:code => course.code, :edition => course.edition)
31
40
  end
32
41
 
33
- def empty?
34
- standards.empty?
35
- end
42
+ private
36
43
 
37
44
  def sol_titles
38
45
  ['English', 'History and Social Science', 'Mathematics', 'Science']
39
46
  end
40
47
 
41
- def sols
42
- @sols ||= select { |s| sol_titles.include?(s.title) }
48
+ def standards
49
+ @standards ||= get_attr(:standards).
50
+ sort_by { |s| s[:title] }.
51
+ collect do |raw_standard|
52
+ Standard.new(raw_standard.merge(:code => code, :edition => edition))
53
+ end
43
54
  end
44
55
 
45
- def non_sols
46
- @non_sols ||= reject { |s| sol_titles.include?(s.title) }
56
+ def path
57
+ "/courses/#{code},#{edition}/standards/"
47
58
  end
48
59
  end
49
60
  end
@@ -1,30 +1,65 @@
1
1
  module Verso
2
- class Task
3
- include HTTPGet
2
+ # Task resource
3
+ #
4
+ # A {Verso::Course} task/competency contained by a {Verso::DutyArea} or
5
+ # a {Verso::CorrelationList}.
6
+ #
7
+ # @!attribute [r] code
8
+ # @return [String] Course code
9
+ # @!attribute [r] definition
10
+ # @return [String] HTML-formatted Task definition
11
+ # @!attribute [r] edition
12
+ # @return [String] Course edition year
13
+ # @!attribute [r] id
14
+ # @return [Fixnum] Task ID
15
+ # @!attribute [r] sensitive
16
+ # @return [Boolean] Is this task sensitive?
17
+ # @!attribute [r] statement
18
+ # @return [String] Task/competency statement
19
+ # @!attribute [r] questions
20
+ # @return [String] HTML-formatted process/skill questions
21
+ #
22
+ # @overload initialize(attrs={})
23
+ # @note Any attributes may be set upon instantiation, using Options Hash.
24
+ # The following are required:
25
+ # @option attrs [String] :code Course code *Required*
26
+ # @option attrs [String] :edition Edition year *Required*
27
+ # @option attrs [String] :id Task ID *Required*
28
+ class Task < Verso::Base
29
+ include HTTPGettable
30
+ attr_reader :code, :definition, :edition, :id, :sensitive, :statement,
31
+ :questions
32
+ alias sensitive? sensitive
4
33
 
5
- def initialize(raw_task)
6
- @raw_task = raw_task
7
- end
8
-
9
- def method_missing(mname)
10
- if !@raw_task.has_key?(mname.to_s)
11
- @raw_task.merge!(JSON.parse(
12
- http_get("/courses/#{code},#{edition}/tasks/#{id}")
13
- ))
14
- end
15
- @raw_task[mname.to_s]
34
+ # @return [Boolean] Does this task have only a statement?
35
+ def bare?
36
+ definition.empty? && standards.sols.empty?
16
37
  end
17
38
 
39
+ # @return [Boolean] Is this task considered essential?
18
40
  def essential
19
- sensitive ? true : @raw_task["essential"]
41
+ sensitive ? true : get_attr(:essential)
20
42
  end
43
+ alias essential? essential
21
44
 
45
+ # @return [Verso::StandardsList] Standards related to this task
22
46
  def standards
23
- @standards ||= StandardsList.new(goals)
47
+ # Yuck. Inject goals if we already have them, i.e. a correlation list.
48
+ # Otherwise, children will fetch resources and we get *all* the
49
+ # standards in the correlation lists.
50
+ raw_goals = get_attr(:goals).collect do |k,v|
51
+ v.merge(:name => k, :code => code, :edition => edition)
52
+ end
53
+ @standards ||= StandardsList.new(
54
+ :code => code, :edition => edition, :standards => raw_goals
55
+ )
24
56
  end
57
+ alias goals standards
25
58
 
26
- def bare?
27
- definition.empty? && standards.sols.empty?
59
+ private
60
+
61
+ def path
62
+ "/courses/#{code},#{edition}/tasks/#{id}"
28
63
  end
29
64
  end
30
65
  end
@@ -1,31 +1,54 @@
1
1
  module Verso
2
- class TaskList
2
+ # Task List resource
3
+ #
4
+ # A collection of {Verso::DutyArea} objects containing the {Verso::Task}
5
+ # objects for a {Verso::Course}
6
+ #
7
+ # @see http://api.cteresource.org/docs/courses/course/tasks
8
+ #
9
+ # @!attribute [r] code
10
+ # @return [String] Course code
11
+ # @!attribute [r] edition
12
+ # @return [String] Course edition
13
+ #
14
+ # @overload initialize(attrs={})
15
+ # @note Attributes required:
16
+ # @option attrs [String] :code Course code *Required*
17
+ # @option attrs [String] :edition Edition year *Required*
18
+ class TaskList < Verso::Base
3
19
  include Enumerable
4
- include HTTPGet
5
-
6
- attr_accessor :code, :edition
7
-
8
- def initialize(params)
9
- @code = params[:code]
10
- @edition = params[:edition]
11
- end
12
-
13
- def duty_areas
14
- @duty_areas ||= JSON.parse(
15
- http_get("/courses/#{code},#{edition}/tasks/")
16
- )["duty_areas"].to_a
17
- end
20
+ include HTTPGettable
21
+ extend Forwardable
22
+ def_delegators :duty_areas, :[], :each, :empty?, :last, :length
23
+ attr_reader :code, :edition
18
24
 
25
+ # @return [Boolean] Contains non-essential tasks?
19
26
  def has_optional_task?
20
27
  any? { |da| da.tasks.any? { |t| !t.essential } }
21
28
  end
22
29
 
30
+ # @return [Boolean] Contains sensitive tasks?
23
31
  def has_sensitive_task?
24
32
  any? { |da| da.tasks.any? { |t| t.sensitive } }
25
33
  end
26
34
 
27
- def each &block
28
- duty_areas.each { |da| block.call(DutyArea.new(da, self)) }
35
+ private
36
+
37
+ def duty_areas
38
+ @duty_areas ||= begin
39
+ get_attr(:duty_areas).
40
+ collect do |da|
41
+ DutyArea.new(
42
+ da.merge!(:code => code, :edition => edition)
43
+ )
44
+ end
45
+ rescue NameError
46
+ []
47
+ end
48
+ end
49
+
50
+ def path
51
+ "/courses/#{code},#{edition}/tasks/"
29
52
  end
30
53
  end
31
54
  end
@@ -1,3 +1,3 @@
1
1
  module Verso
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end