academic_benchmarks 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c13cf6be09fd07cb0109d047e350f67b5d4cbc26
4
+ data.tar.gz: 64e6b5f20059e2d4a3cb9fa80e2fb646368eb8bd
5
+ SHA512:
6
+ metadata.gz: 3dd28dee3d000f68bedf3b0f096ad3373946fd908bb38ed0eec10d6900d8fc0851243df23eed7dca4354a4b4a698f5542d4eff0ce7158e58b3fb70840becb1d3
7
+ data.tar.gz: b9064ef02deddcef55face091a4212ce4e83a6b4f83189428ad5b9eb75b22d184404a43a17195ee463db3b7353701b98b07fe191dc7f1541ff2037b0cc10be48
@@ -0,0 +1,13 @@
1
+ require 'httparty'
2
+ require 'json'
3
+ require 'base64'
4
+ require 'openssl'
5
+
6
+ begin
7
+ require 'byebug'
8
+ rescue LoadError => e
9
+ end
10
+
11
+ Gem.find_files("academic_benchmarks/**/*.rb").each do |path|
12
+ require path.gsub(/\.rb$/, '')
13
+ end
@@ -0,0 +1,46 @@
1
+ require 'active_support/core_ext/numeric/time'
2
+
3
+ module AcademicBenchmarks
4
+ module Api
5
+ module Auth
6
+ def self.auth_query_params(partner_id:, partner_key:, expires:, user_id: "")
7
+ {
8
+ "partner.id" => partner_id,
9
+ "auth.signature" => signature_for(
10
+ partner_key: partner_key,
11
+ message: self.message(expires: expires, user_id: user_id)),
12
+ "auth.expires" => expires,
13
+ "user.id" => user_id
14
+ }
15
+ end
16
+
17
+ def self.signature_for(partner_key:, message:)
18
+ Base64.encode64(OpenSSL::HMAC.digest(
19
+ OpenSSL::Digest.new('sha256'),
20
+ partner_key,
21
+ message
22
+ )).chomp
23
+ end
24
+
25
+ def self.message(expires:, user_id: '')
26
+ if user_id.empty?
27
+ "#{expires}"
28
+ else
29
+ "#{expires}\n#{user_id}"
30
+ end
31
+ end
32
+
33
+ def self.expire_time_in_10_seconds
34
+ self.expire_time_in(10.seconds)
35
+ end
36
+
37
+ def self.expire_time_in_2_hours
38
+ self.expire_time_in(2.hours)
39
+ end
40
+
41
+ def self.expire_time_in(offset)
42
+ Time.now.to_i + offset
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,43 @@
1
+ module AcademicBenchmarks
2
+ module Api
3
+ module Constants
4
+ def self.base_url
5
+ 'https://api.academicbenchmarks.com/rest/v3'
6
+ end
7
+
8
+ def self.api_version
9
+ '3'
10
+ end
11
+
12
+ def self.partner_id_env_var
13
+ 'ACADEMIC_BENCHMARKS_PARTNER_ID'
14
+ end
15
+
16
+ def self.partner_key_env_var
17
+ 'ACADEMIC_BENCHMARKS_PARTNER_KEY'
18
+ end
19
+
20
+ def self.user_id_env_var
21
+ 'ACADEMIC_BENCHMARKS_USER_ID'
22
+ end
23
+
24
+ def self.standards_search_params
25
+ %w[
26
+ query
27
+ authority
28
+ subject
29
+ grade
30
+ subject_doc
31
+ course
32
+ document
33
+ parent
34
+ deepest
35
+ limit
36
+ offset
37
+ list
38
+ fields
39
+ ]
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,92 @@
1
+ require_relative 'constants'
2
+ require_relative 'standards'
3
+
4
+ module AcademicBenchmarks
5
+ module Api
6
+ class Handle
7
+ include HTTParty
8
+
9
+ attr_accessor :partner_id, :partner_key
10
+
11
+ attr_reader :user_id # user_id writer is defined below
12
+
13
+ base_uri AcademicBenchmarks::Api::Constants.base_url
14
+
15
+ # Allows the user to initialize from environment variables
16
+ def self.init_from_env
17
+ partner_id = partner_id_from_env
18
+ partner_key = partner_key_from_env
19
+
20
+ if !partner_id.present? || !partner_key.present?
21
+ pidstr = !partner_id.present? ?
22
+ AcademicBenchmarks::Api::Constants.partner_id_env_var : ""
23
+ pkystr = !partner_key.present? ?
24
+ AcademicBenchmarks::Api::Constants.partner_key_env_var : ""
25
+ raise StandardError.new(
26
+ "Missing environment variable(s): #{[pidstr, pkystr].join(', ')}"
27
+ )
28
+ end
29
+
30
+ new(
31
+ partner_id: partner_id,
32
+ partner_key: partner_key,
33
+ user_id: user_id_from_env
34
+ )
35
+ end
36
+
37
+ def initialize(partner_id:, partner_key:, user_id: "")
38
+ @partner_id = partner_id
39
+ @partner_key = partner_key
40
+ @user_id = user_id.to_s
41
+ end
42
+
43
+ def user_id=(user_id)
44
+ @user_id = user_id.to_s
45
+ end
46
+
47
+ def related(guid:, fields: [])
48
+ raise StandardError.new("Sorry, not implemented yet!")
49
+ end
50
+
51
+ def standards
52
+ Standards.new(self)
53
+ end
54
+
55
+ def assets
56
+ raise StandardError.new("Sorry, not implemented yet!")
57
+ end
58
+
59
+ def alignments
60
+ raise StandardError.new("Sorry, not implemented yet!")
61
+ end
62
+
63
+ def topics
64
+ raise StandardError.new("Sorry, not implemented yet!")
65
+ end
66
+
67
+ def special
68
+ raise StandardError.new("Sorry, not implemented yet!")
69
+ end
70
+
71
+ private
72
+
73
+ def api_resp_to_array_of_standards(api_resp)
74
+ api_resp.parsed_response["resources"].inject([]) do |retval, resource|
75
+ retval.push(AcademicBenchmarks::Standards::Standard.new(resource["data"]))
76
+ end
77
+ end
78
+
79
+ def self.partner_id_from_env
80
+ ENV[AcademicBenchmarks::Api::Constants.partner_id_env_var]
81
+ end
82
+
83
+ def self.partner_key_from_env
84
+ ENV[AcademicBenchmarks::Api::Constants.partner_key_env_var]
85
+ end
86
+
87
+ def self.user_id_from_env
88
+ ENV[AcademicBenchmarks::Api::Constants.user_id_env_var]
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,128 @@
1
+ require 'active_support/hash_with_indifferent_access'
2
+
3
+ require_relative 'auth'
4
+ require_relative 'constants'
5
+
6
+ module AcademicBenchmarks
7
+ module Api
8
+ class Standards
9
+ DEFAULT_PER_PAGE = 100
10
+
11
+ def initialize(handle)
12
+ @handle = handle
13
+ end
14
+
15
+ def search(opts = {})
16
+ # query: "", authority: "", subject: "", grade: "", subject_doc: "", course: "",
17
+ # document: "", parent: "", deepest: "", limit: -1, offset: -1, list: "", fields: []
18
+ invalid_params = invalid_search_params(opts)
19
+ if invalid_params.empty?
20
+ raw_search(opts).map do |standard|
21
+ AcademicBenchmarks::Standards::Standard.new(standard)
22
+ end
23
+ else
24
+ raise ArgumentError.new(
25
+ "Invalid search params: #{invalid_params.join(', ')}"
26
+ )
27
+ end
28
+ end
29
+
30
+ alias_method :where, :search
31
+
32
+ def guid(guid, fields: [])
33
+ query_params = if fields.empty?
34
+ auth_query_params
35
+ else
36
+ auth_query_params.merge({
37
+ fields: fields.join(",")
38
+ })
39
+ end
40
+ @handle.class.get(
41
+ "/standards/#{guid}",
42
+ query: query_params
43
+ ).parsed_response["resources"].map do |r|
44
+ AcademicBenchmarks::Standards::Standard.new(r["data"])
45
+ end
46
+ end
47
+
48
+ def all
49
+ request_search_pages_and_concat_resources(auth_query_params)
50
+ end
51
+
52
+ def authorities
53
+ raw_search(list: "authority").map{|a| a["data"]["authority"]}.map{|a| AcademicBenchmarks::Standards::Authority.from_hash(a)}
54
+ end
55
+
56
+ private
57
+
58
+ def raw_search(opts = {})
59
+ request_search_pages_and_concat_resources(opts.merge(auth_query_params))
60
+ end
61
+
62
+ def invalid_search_params(opts)
63
+ opts.keys.map(&:to_s) - AcademicBenchmarks::Api::Constants.standards_search_params
64
+ end
65
+
66
+ def auth_query_params
67
+ AcademicBenchmarks::Api::Auth.auth_query_params(
68
+ partner_id: @handle.partner_id,
69
+ partner_key: @handle.partner_key,
70
+ expires: AcademicBenchmarks::Api::Auth.expire_time_in_2_hours,
71
+ user_id: @handle.user_id
72
+ )
73
+ end
74
+
75
+ def request_search_pages_and_concat_resources(query_params)
76
+ query_params.reverse_merge!({limit: DEFAULT_PER_PAGE})
77
+
78
+ if !query_params[:limit] || query_params[:limit] <= 0
79
+ raise ArgumentError.new(
80
+ "limit must be specified as a positive integer"
81
+ )
82
+ end
83
+
84
+ first_page = request_page(
85
+ query_params: query_params,
86
+ limit: query_params[:limit],
87
+ offset: 0
88
+ ).parsed_response
89
+
90
+ resources = first_page["resources"]
91
+ count = first_page["count"]
92
+ offset = query_params[:limit]
93
+
94
+ while offset < count
95
+ page = request_page(
96
+ query_params: query_params,
97
+ limit: query_params[:limit],
98
+ offset: offset
99
+ )
100
+ offset += query_params[:limit]
101
+ resources.push(page.parsed_response["resources"])
102
+ end
103
+
104
+ resources.flatten
105
+ end
106
+
107
+ def request_page(query_params:, limit:, offset:)
108
+ query_params.merge!({
109
+ limit: limit,
110
+ offset: offset,
111
+ })
112
+ resp = @handle.class.get(
113
+ '/standards',
114
+ query: query_params.merge({
115
+ limit: limit,
116
+ offset: offset,
117
+ })
118
+ )
119
+ if resp.code != 200
120
+ raise RuntimeError.new(
121
+ "Received response '#{resp.code}: #{resp.message}' requesting standards from Academic Benchmarks:"
122
+ )
123
+ end
124
+ resp
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,14 @@
1
+
2
+ module InstVarsToHash
3
+ def to_s
4
+ to_h.to_s
5
+ end
6
+
7
+ def to_h
8
+ retval = {}
9
+ instance_variables.each do |iv|
10
+ retval[iv.to_s.gsub('@', '').to_sym] = instance_variable_get(iv)
11
+ end
12
+ retval
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ require_relative '../lib/inst_vars_to_hash'
2
+
3
+ module AcademicBenchmarks
4
+ module Standards
5
+ class Authority
6
+ include InstVarsToHash
7
+
8
+ attr_accessor :code, :guid, :description
9
+
10
+ alias_method :descr, :description
11
+
12
+ def self.from_hash(hash)
13
+ self.new(code: hash["code"], guid: hash["guid"], description: hash["descr"])
14
+ end
15
+
16
+ def initialize(code:, guid:, description:)
17
+ @code = code
18
+ @guid = guid
19
+ @description = description
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ require_relative '../lib/inst_vars_to_hash'
2
+
3
+ module AcademicBenchmarks
4
+ module Standards
5
+ class Course
6
+ include InstVarsToHash
7
+
8
+ attr_accessor :guid, :description
9
+
10
+ alias_method :descr, :description
11
+
12
+ def self.from_hash(hash)
13
+ self.new(description: hash["descr"], guid: hash["guid"])
14
+ end
15
+
16
+ def initialize(guid:, description:)
17
+ @guid = guid
18
+ @description = description
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ require_relative '../lib/inst_vars_to_hash'
2
+
3
+ module AcademicBenchmarks
4
+ module Standards
5
+ class Document
6
+ include InstVarsToHash
7
+
8
+ attr_accessor :title, :guid
9
+
10
+ def self.from_hash(hash)
11
+ self.new(title: hash["title"], guid: hash["guid"])
12
+ end
13
+
14
+ def initialize(title:, guid:)
15
+ @title = title
16
+ @guid = guid
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require_relative '../lib/inst_vars_to_hash'
2
+
3
+ module AcademicBenchmarks
4
+ module Standards
5
+ class Grade
6
+ include InstVarsToHash
7
+
8
+ attr_accessor :high, :low
9
+
10
+ def self.from_hash(hash)
11
+ self.new(high: hash["high"], low: hash["low"])
12
+ end
13
+
14
+ def initialize(high:, low:)
15
+ @high = high
16
+ @low = low
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ require_relative '../lib/inst_vars_to_hash'
2
+
3
+ module AcademicBenchmarks
4
+ module Standards
5
+ class HasRelations
6
+ include InstVarsToHash
7
+
8
+ attr_accessor :origin, :derivative, :related_derivative
9
+
10
+ def self.from_hash(hash)
11
+ self.new(derivative: hash["derivative"], origin: hash["origin"], related_derivative: hash["related_derivative"])
12
+ end
13
+
14
+ def initialize(origin: 0, derivative: 0, related_derivative: 0)
15
+ @origin = origin
16
+ @derivative = derivative
17
+ @related_derivative = related_derivative
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ require_relative '../lib/inst_vars_to_hash'
2
+
3
+ module AcademicBenchmarks
4
+ module Standards
5
+ class Parent
6
+ include InstVarsToHash
7
+
8
+ attr_accessor :guid, :description, :number, :stem, :label, :deepest,
9
+ :seq, :level, :status, :version
10
+
11
+ def self.from_hash(hash)
12
+ self.new(
13
+ guid: hash["guid"],
14
+ description: hash["description"],
15
+ number: hash["number"],
16
+ stem: hash["stem"],
17
+ label: hash["label"],
18
+ deepest: hash["deepest"],
19
+ seq: hash["seq"],
20
+ level: hash["level"],
21
+ status: hash["status"],
22
+ version: hash["version"]
23
+ )
24
+ end
25
+
26
+ def initialize(guid:, description:, number:, stem:, label:, deepest:,
27
+ seq:, level:, status:, version:)
28
+ @guid = guid
29
+ @description = description
30
+ @number = number
31
+ @stem = stem
32
+ @label = label
33
+ @deepest = deepest
34
+ @seq = seq
35
+ @level = level
36
+ @status = status
37
+ @version = version
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,96 @@
1
+ require_relative '../lib/inst_vars_to_hash'
2
+
3
+ module AcademicBenchmarks
4
+ module Standards
5
+ class Standard
6
+ include InstVarsToHash
7
+
8
+ attr_reader :status, :deepest, :children
9
+ attr_accessor :guid, :description, :number, :stem, :label, :level,
10
+ :version, :seq, :adopt_year, :authority, :course,
11
+ :document, :grade, :has_relations, :subject,
12
+ :subject_doc, :parent, :parent_guid
13
+
14
+ alias_method :descr, :description
15
+
16
+ def initialize(data)
17
+ data = data["data"] if data["data"]
18
+ @guid = data["guid"]
19
+ @grade = attr_to_val_or_nil(Grade, data, "grade")
20
+ @label = data["label"]
21
+ @level = data["level"]
22
+ @course = attr_to_val_or_nil(Course, data, "course")
23
+ @number = data["number"]
24
+ @status = data["status"]
25
+ @parent = nil
26
+ @subject = attr_to_val_or_nil(Subject, data, "subject")
27
+ @deepest = data["deepest"]
28
+ @version = data["version"]
29
+ @children = []
30
+ @document = attr_to_val_or_nil(Document, data, "document")
31
+ @authority = attr_to_val_or_nil(Authority, data, "authority")
32
+ @adopt_year = data["adopt_year"]
33
+ @description = data["descr"]
34
+ @subject_doc = attr_to_val_or_nil(SubjectDoc, data, "subject_doc")
35
+ @has_relations = attr_to_val_or_nil(HasRelations, data, "has_relations")
36
+
37
+ # Parent guid extraction can be a little more complicated. Thanks AB!
38
+ if data["parent"] && data["parent"].is_a?(String)
39
+ @parent_guid = data["parent"]
40
+ elsif data["parent"] && data["parent"].is_a?(Hash)
41
+ @parent_guid = data["parent"]["guid"]
42
+ end
43
+ end
44
+
45
+ def active?
46
+ status == "Active"
47
+ end
48
+
49
+ def obsolete?
50
+ status == "Obsolete"
51
+ end
52
+
53
+ def deepest?
54
+ deepest == 'Y'
55
+ end
56
+
57
+ def status=(status)
58
+ unless %w[Active Obsolete].include?(status)
59
+ raise ArgumentError.new(
60
+ "Standard status must be either 'Active' or 'Obsolete'"
61
+ )
62
+ end
63
+ @status = status
64
+ end
65
+
66
+ def deepest=(deepest)
67
+ unless %w[Y N].include?(deepest)
68
+ raise ArgumentError.new("Standard deepest must be either 'Y' or 'N'")
69
+ end
70
+ @deepest = deepest
71
+ end
72
+
73
+ def add_child(child)
74
+ unless child.is_a?(Standard)
75
+ raise ArgumentError.new("Tried to set child that isn't a Standard")
76
+ end
77
+ @children.push(child)
78
+ end
79
+
80
+ def remove_child(child)
81
+ @children.delete(child)
82
+ end
83
+
84
+ def has_children?
85
+ @children.count > 0
86
+ end
87
+
88
+ private
89
+
90
+ def attr_to_val_or_nil(klass, hash, attr)
91
+ return nil unless hash.has_key?(attr)
92
+ klass.from_hash(hash)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,97 @@
1
+ module AcademicBenchmarks
2
+ module Standards
3
+ class StandardsForest
4
+ attr_reader :trees, :data_hash
5
+
6
+ # The guid to standard hash can optionally be saved to permit speedily
7
+ # adding standards to the tree (since the tree is unordered,
8
+ # this would otherwise be an expensive operation).
9
+ #
10
+ # The initial data hash can also be optionally saved to
11
+ # permit testing and internal consistency checks
12
+
13
+ def initialize(
14
+ data_hash,
15
+ save_guid_to_standard_hash: true,
16
+ save_initial_data_hash: false
17
+ )
18
+ @data_hash = data_hash.dup.freeze if save_initial_data_hash
19
+ @guid_to_standard = {} # a hash of guids to standards
20
+ @trees = []
21
+ process_items(data_hash)
22
+
23
+ # upgrade the hash data to a StandardsTree object
24
+ @trees.map! do |item|
25
+ StandardsTree.new(item, build_item_hash: save_guid_to_standard_hash)
26
+ end
27
+
28
+ unless save_guid_to_standard_hash
29
+ remove_instance_variable('@guid_to_standard')
30
+ end
31
+ end
32
+
33
+ def add_standard(standard)
34
+ if standard.is_a?(Standard)
35
+ raise StandardError.new(
36
+ "adding standards is not currently implemented"
37
+ )
38
+ elsif standard.is_a?(Hash)
39
+ add_standard(Standard.new(standard))
40
+ else
41
+ raise ArgumentError.new(
42
+ "standard must be an 'AcademicBenchmarks::Standards::Standard' " \
43
+ "or a 'Hash' but was a #{standard.class.to_s}"
44
+ )
45
+ end
46
+ end
47
+
48
+ def single_tree?
49
+ @trees.count == 1
50
+ end
51
+
52
+ def empty?
53
+ @trees.empty?
54
+ end
55
+
56
+ private
57
+
58
+ def to_standard(item)
59
+ return item if item.is_a?(Standard)
60
+ Standard.new(item)
61
+ end
62
+
63
+ def process_items(data_hash)
64
+ build_guid_to_standard_hash(data_hash)
65
+ link_parent_and_children
66
+ end
67
+
68
+ def build_guid_to_standard_hash(data_hash)
69
+ data_hash.each do |item|
70
+ item = to_standard(item)
71
+ @guid_to_standard[item.guid] = item
72
+ end
73
+ end
74
+
75
+ def link_parent_and_children
76
+ @guid_to_standard.values.each do |child|
77
+ if child.parent_guid
78
+ present_in_hash_or_raise(child.parent_guid)
79
+ parent = @guid_to_standard[child.parent_guid]
80
+ parent.add_child(child)
81
+ child.parent = parent
82
+ else
83
+ @trees.push(child)
84
+ end
85
+ end
86
+ end
87
+
88
+ def present_in_hash_or_raise(guid)
89
+ unless @guid_to_standard.has_key?(guid)
90
+ raise StandardError.new(
91
+ "item missing from guid_to_standard hash"
92
+ )
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,67 @@
1
+ module AcademicBenchmarks
2
+ module Standards
3
+ class StandardsTree
4
+ attr_reader :root_standard
5
+
6
+ # The item hash can optionally be built to permit the speedy
7
+ # addition of standards to the tree. since the tree is unordered,
8
+ # adding to it can be expensive without this
9
+
10
+ def initialize(root_standard, build_item_hash: true)
11
+ @root_standard = root_standard
12
+ if build_item_hash
13
+ @item_hash = {}
14
+ go_ahead_and_build_item_hash
15
+ end
16
+ end
17
+
18
+ def add_standard(standard)
19
+ if standard.is_a?(Standard)
20
+ parent = @item_hash ? @item_hash[standard.parent_guid] : find_parent(standard)
21
+ unless parent
22
+ raise StandardError.new(
23
+ "Parent of standard not found in tree. Parent guid is " \
24
+ "'#{standard.parent_guid}' and child guid is '#{standard.guid}'"
25
+ )
26
+ end
27
+ parent.add_child(standard)
28
+ standard.parent = parent
29
+ elsif standard.is_a?(Hash)
30
+ add_standard(Standard.new(standard))
31
+ else
32
+ raise ArgumentError.new(
33
+ "standard must be an 'AcademicBenchmarks::Standards::Standard' " \
34
+ "or a 'Hash' but was a #{standard.class.to_s}"
35
+ )
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def go_ahead_and_build_item_hash
42
+ @item_hash[@root_standard.guid] = @root_standard
43
+ add_children_to_item_hash(@root_standard)
44
+ end
45
+
46
+ def add_children_to_item_hash(parent)
47
+ parent.children.each do |child|
48
+ @item_hash[child.guid] = child
49
+ add_children_to_item_hash(child) if child.has_children?
50
+ end
51
+ end
52
+
53
+ def find_parent(standard)
54
+ return @root_standard if @root_standard.guid == standard.parent_guid
55
+ check_children_for_parent(standard.parent_guid, @root_standard)
56
+ end
57
+
58
+ # does a depth-first search
59
+ def check_children_for_parent(parent_guid, standard)
60
+ standard.children.each do |child|
61
+ return child if child.guid == parent_guid
62
+ check_children_for_parent(parent_guid, child) if child.has_children?
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,20 @@
1
+ require_relative '../lib/inst_vars_to_hash'
2
+
3
+ module AcademicBenchmarks
4
+ module Standards
5
+ class Subject
6
+ include InstVarsToHash
7
+
8
+ attr_accessor :code, :broad
9
+
10
+ def self.from_hash(hash)
11
+ self.new(code: hash["code"], broad: hash["broad"], )
12
+ end
13
+
14
+ def initialize(code:, broad:)
15
+ @code = code
16
+ @broad = broad
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ require_relative '../lib/inst_vars_to_hash'
2
+
3
+ module AcademicBenchmarks
4
+ module Standards
5
+ class SubjectDoc
6
+ include InstVarsToHash
7
+
8
+ attr_accessor :guid, :description
9
+
10
+ alias_method :descr, :description
11
+
12
+ def self.from_hash(hash)
13
+ self.new(guid: hash["guid"], description: hash["descr"])
14
+ end
15
+
16
+ def initialize(guid:, description:)
17
+ @guid = guid
18
+ @description = description
19
+ end
20
+ end
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: academic_benchmarks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Benjamin Porter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.13'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: awesome_print
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.6'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.6'
83
+ description: A ruby api for accessing the Academic Benchmarks API. A valid subscription
84
+ with accompanying credentials will be required to access the API
85
+ email: bporter@instructure.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - lib/academic_benchmarks.rb
91
+ - lib/academic_benchmarks/api/auth.rb
92
+ - lib/academic_benchmarks/api/constants.rb
93
+ - lib/academic_benchmarks/api/handle.rb
94
+ - lib/academic_benchmarks/api/standards.rb
95
+ - lib/academic_benchmarks/lib/inst_vars_to_hash.rb
96
+ - lib/academic_benchmarks/standards/authority.rb
97
+ - lib/academic_benchmarks/standards/course.rb
98
+ - lib/academic_benchmarks/standards/document.rb
99
+ - lib/academic_benchmarks/standards/grade.rb
100
+ - lib/academic_benchmarks/standards/has_relations.rb
101
+ - lib/academic_benchmarks/standards/parent.rb
102
+ - lib/academic_benchmarks/standards/standard.rb
103
+ - lib/academic_benchmarks/standards/standards_forest.rb
104
+ - lib/academic_benchmarks/standards/standards_tree.rb
105
+ - lib/academic_benchmarks/standards/subject.rb
106
+ - lib/academic_benchmarks/standards/subject_doc.rb
107
+ homepage: https://github.com/instructure/academic_benchmarks
108
+ licenses:
109
+ - GPL
110
+ metadata: {}
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 2.2.3
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: A ruby api for accessing the Academic Benchmarks API
131
+ test_files: []
132
+ has_rdoc: