bright 1.3 → 2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Rakefile +0 -1
- data/bright.gemspec +12 -14
- data/lib/bright/address.rb +5 -5
- data/lib/bright/connection.rb +7 -9
- data/lib/bright/contact.rb +7 -9
- data/lib/bright/cursor_response_collection.rb +8 -10
- data/lib/bright/email_address.rb +1 -2
- data/lib/bright/enrollment.rb +2 -2
- data/lib/bright/errors.rb +0 -1
- data/lib/bright/helpers/blank_helper.rb +0 -2
- data/lib/bright/model.rb +13 -13
- data/lib/bright/phone_number.rb +1 -2
- data/lib/bright/response_collection.rb +8 -8
- data/lib/bright/school.rb +1 -4
- data/lib/bright/sis_apis/aeries.rb +18 -19
- data/lib/bright/sis_apis/base.rb +3 -5
- data/lib/bright/sis_apis/bright_sis.rb +82 -84
- data/lib/bright/sis_apis/focus.rb +78 -84
- data/lib/bright/sis_apis/one_roster/infinite_campus.rb +15 -0
- data/lib/bright/sis_apis/one_roster/skyward.rb +6 -0
- data/lib/bright/sis_apis/{infinite_campus.rb → one_roster.rb} +91 -100
- data/lib/bright/sis_apis/power_school.rb +105 -107
- data/lib/bright/sis_apis/synergy.rb +6 -8
- data/lib/bright/sis_apis/tsis.rb +54 -54
- data/lib/bright/student.rb +15 -19
- data/lib/bright/version.rb +1 -1
- data/lib/bright.rb +14 -12
- metadata +6 -5
- data/lib/bright/sis_apis/skyward.rb +0 -277
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2478a62cb11741cb1406e3f38bd2e387beb5f042c2c8e170d455e7d531d779b
|
4
|
+
data.tar.gz: 507582c1502e2894e470236fedeba7efcd906d9a29d15a5c4d6218b1468666ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b07d3fee51e60da6f25f84cb2ba4a275d7597da0fc481866e5c838a7bbdeb63b4c80c22de44f145f91becc22e53ea5ee50d888aa931517c142fb199f277d32c
|
7
|
+
data.tar.gz: 934e5d22043fc74251b2321532897cbff7d06e63b722321e99fb00ca2711d23abfc853234642bb6c72db2dddcafad58d324a5e0251c9f36a42e2755df18eb765
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/bright.gemspec
CHANGED
@@ -1,21 +1,19 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
3
|
+
require "bright/version"
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name
|
8
|
-
spec.version
|
9
|
-
spec.authors
|
10
|
-
spec.email
|
11
|
-
spec.summary
|
12
|
-
spec.description
|
13
|
-
spec.homepage
|
14
|
-
spec.license
|
6
|
+
spec.name = "bright"
|
7
|
+
spec.version = Bright::VERSION
|
8
|
+
spec.authors = ["Arux Software"]
|
9
|
+
spec.email = ["hello@arux.software"]
|
10
|
+
spec.summary = "Framework and tools for dealing with Student Information Systems"
|
11
|
+
spec.description = "Bright is a simple Student Information System API abstraction library used in and sponsored by Arux Software. It is written by Stephen Heuer, Steven Novotny, and contributors. The aim of the project is to abstract as many parts as possible away from the user to offer a consistent interface across all supported Student Information System APIs."
|
12
|
+
spec.homepage = "https://github.com/Arux-Software/Bright"
|
13
|
+
spec.license = "MIT"
|
15
14
|
|
16
|
-
spec.files
|
17
|
-
spec.executables
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
17
|
spec.require_paths = ["lib"]
|
20
18
|
|
21
19
|
spec.add_runtime_dependency "httpi", "~> 2.1"
|
data/lib/bright/address.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
module Bright
|
2
2
|
class Address < Model
|
3
3
|
@attribute_names = [:street, :apt, :city, :state, :postal_code, :latitude, :longitude, :type]
|
4
|
-
attr_accessor
|
4
|
+
attr_accessor(*@attribute_names)
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
alias_method :lat, :latitude
|
7
|
+
alias_method :lng, :longitude
|
8
8
|
|
9
9
|
def geographical_coordinates
|
10
|
-
if
|
11
|
-
"#{
|
10
|
+
if latitude and longitude
|
11
|
+
"#{latitude},#{longitude}"
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
data/lib/bright/connection.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "uri"
|
2
|
+
require "httpi"
|
3
|
+
require "benchmark"
|
4
|
+
require "securerandom"
|
5
5
|
|
6
6
|
module Bright
|
7
7
|
class Connection
|
@@ -23,10 +23,10 @@ module Bright
|
|
23
23
|
attr_accessor :proxy_port
|
24
24
|
|
25
25
|
def initialize(endpoint)
|
26
|
-
@endpoint
|
26
|
+
@endpoint = endpoint.is_a?(URI) ? endpoint : URI.parse(endpoint)
|
27
27
|
@open_timeout = OPEN_TIMEOUT
|
28
28
|
@read_timeout = READ_TIMEOUT
|
29
|
-
@verify_peer
|
29
|
+
@verify_peer = VERIFY_PEER
|
30
30
|
@ignore_http_status = false
|
31
31
|
@ssl_version = nil
|
32
32
|
@proxy_address = nil
|
@@ -36,7 +36,6 @@ module Bright
|
|
36
36
|
@logger = Logger.new(STDOUT)
|
37
37
|
@logger.level = Logger::INFO
|
38
38
|
end
|
39
|
-
|
40
39
|
end
|
41
40
|
|
42
41
|
def request(method, body, headers = {})
|
@@ -83,7 +82,6 @@ module Bright
|
|
83
82
|
end
|
84
83
|
|
85
84
|
handle_response(result)
|
86
|
-
|
87
85
|
ensure
|
88
86
|
info "connection_request_total_time=%.4fs" % [Time.now.to_f - request_start], tag
|
89
87
|
end
|
@@ -101,7 +99,7 @@ module Bright
|
|
101
99
|
|
102
100
|
def handle_response(response)
|
103
101
|
if @ignore_http_status or !response.error?
|
104
|
-
|
102
|
+
response
|
105
103
|
else
|
106
104
|
raise ResponseError.new(response, endpoint.to_s)
|
107
105
|
end
|
data/lib/bright/contact.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require
|
1
|
+
require "securerandom"
|
2
2
|
|
3
3
|
module Bright
|
4
4
|
class Contact < Model
|
5
5
|
@attribute_names = [:client_id, :api_id, :first_name, :middle_name, :last_name, :nick_name,
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
attr_accessor
|
6
|
+
:birth_date, :sex, :relationship_type,
|
7
|
+
:hispanic_ethnicity, :race, :image,
|
8
|
+
:sis_student_id, :state_student_id, :last_modified]
|
9
|
+
attr_accessor(*@attribute_names)
|
10
10
|
|
11
11
|
def self.attribute_names
|
12
12
|
@attribute_names
|
@@ -18,7 +18,7 @@ module Bright
|
|
18
18
|
if array.size <= 0 or array.first.is_a?(PhoneNumber)
|
19
19
|
@phone_numbers = array
|
20
20
|
elsif array.first.is_a?(Hash)
|
21
|
-
@phone_numbers = array.collect{|a| PhoneNumber.new(a)}
|
21
|
+
@phone_numbers = array.collect { |a| PhoneNumber.new(a) }
|
22
22
|
end
|
23
23
|
@phone_numbers ||= []
|
24
24
|
end
|
@@ -31,7 +31,7 @@ module Bright
|
|
31
31
|
if array.size <= 0 or array.first.is_a?(Address)
|
32
32
|
@addresses = array
|
33
33
|
elsif array.first.is_a?(Hash)
|
34
|
-
@addresses = array.collect{|a| Address.new(a)}
|
34
|
+
@addresses = array.collect { |a| Address.new(a) }
|
35
35
|
end
|
36
36
|
@addresses ||= []
|
37
37
|
end
|
@@ -46,8 +46,6 @@ module Bright
|
|
46
46
|
elsif email.is_a?(Hash)
|
47
47
|
@email_address = EmailAddress.new(email)
|
48
48
|
end
|
49
|
-
@email_address
|
50
49
|
end
|
51
|
-
|
52
50
|
end
|
53
51
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
class CursorResponseCollection < ResponseCollection
|
2
|
-
|
3
2
|
attr_accessor :collected_objects
|
4
3
|
|
5
4
|
def initialize(options = {})
|
@@ -10,7 +9,7 @@ class CursorResponseCollection < ResponseCollection
|
|
10
9
|
end
|
11
10
|
|
12
11
|
def each
|
13
|
-
|
12
|
+
until @next_cursor.blank?
|
14
13
|
objects_hsh = load_more_call.call(@next_cursor)
|
15
14
|
objects = objects_hsh[:objects]
|
16
15
|
@next_cursor = objects_hsh[:next_cursor]
|
@@ -22,8 +21,8 @@ class CursorResponseCollection < ResponseCollection
|
|
22
21
|
end
|
23
22
|
|
24
23
|
def last
|
25
|
-
|
26
|
-
|
24
|
+
to_a
|
25
|
+
@collected_objects.last
|
27
26
|
end
|
28
27
|
|
29
28
|
def loaded_results
|
@@ -31,15 +30,14 @@ class CursorResponseCollection < ResponseCollection
|
|
31
30
|
end
|
32
31
|
|
33
32
|
def total
|
34
|
-
|
35
|
-
|
33
|
+
to_a
|
34
|
+
loaded_results.size
|
36
35
|
end
|
37
36
|
|
38
|
-
|
39
|
-
|
37
|
+
alias_method :size, :total
|
38
|
+
alias_method :length, :total
|
40
39
|
|
41
40
|
def empty?
|
42
|
-
|
41
|
+
to_a.empty?
|
43
42
|
end
|
44
|
-
|
45
43
|
end
|
data/lib/bright/email_address.rb
CHANGED
data/lib/bright/enrollment.rb
CHANGED
data/lib/bright/errors.rb
CHANGED
data/lib/bright/model.rb
CHANGED
@@ -1,33 +1,33 @@
|
|
1
1
|
module Bright
|
2
2
|
class Model
|
3
3
|
@attribute_names = []
|
4
|
-
|
5
|
-
def initialize(attributes={})
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
6
|
assign_attributes(attributes) if attributes
|
7
7
|
|
8
8
|
super()
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def assign_attributes(new_attributes)
|
12
12
|
if !new_attributes.is_a?(Hash)
|
13
13
|
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
|
14
14
|
end
|
15
15
|
return if new_attributes.empty?
|
16
16
|
|
17
|
-
attributes =
|
17
|
+
attributes = new_attributes.collect { |k, v| [k.to_sym, v] }.to_h
|
18
18
|
_assign_attributes(attributes)
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def self.attribute_names
|
22
22
|
@attribute_names
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def to_json
|
26
|
-
|
27
|
-
[n,
|
28
|
-
end
|
26
|
+
self.class.attribute_names.collect do |n|
|
27
|
+
[n, send(n)]
|
28
|
+
end.to_h.to_json
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
private
|
32
32
|
|
33
33
|
def _assign_attributes(attributes)
|
@@ -37,11 +37,11 @@ module Bright
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def _assign_attribute(k, v)
|
40
|
-
if respond_to?("#{k}=")
|
41
|
-
public_send("#{k}=", v)
|
40
|
+
if respond_to?(:"#{k}=")
|
41
|
+
public_send(:"#{k}=", v)
|
42
42
|
else
|
43
43
|
raise UnknownAttributeError.new(self, k)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
47
|
-
end
|
47
|
+
end
|
data/lib/bright/phone_number.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Bright
|
2
2
|
class PhoneNumber < Model
|
3
3
|
@attribute_names = [:phone_number, :extension, :type]
|
4
|
-
attr_accessor
|
4
|
+
attr_accessor(*@attribute_names)
|
5
5
|
TYPES = ["Cell", "Home", "Work", "Other"]
|
6
6
|
|
7
7
|
def phone_number=(number)
|
@@ -15,6 +15,5 @@ module Bright
|
|
15
15
|
def extension=(number)
|
16
16
|
@extension = number.gsub(/[^0-9]/, "").strip
|
17
17
|
end
|
18
|
-
|
19
18
|
end
|
20
19
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "parallel"
|
2
2
|
|
3
3
|
class ResponseCollection
|
4
4
|
include Enumerable
|
@@ -15,7 +15,7 @@ class ResponseCollection
|
|
15
15
|
@paged_objects = {0 => options[:seed_page]}
|
16
16
|
@total = options[:total].to_i
|
17
17
|
@per_page = options[:per_page].to_i
|
18
|
-
@pages = @per_page > 0 ? (@total.to_f / @per_page.to_f).ceil : 0
|
18
|
+
@pages = (@per_page > 0) ? (@total.to_f / @per_page.to_f).ceil : 0
|
19
19
|
@load_more_call = options[:load_more_call]
|
20
20
|
@no_threads = options[:no_threads] || DEFAULT_NO_THREADS
|
21
21
|
end
|
@@ -23,10 +23,10 @@ class ResponseCollection
|
|
23
23
|
def each
|
24
24
|
Parallel.each(0..@pages, in_threads: @no_threads) do |current_page|
|
25
25
|
objects = if @paged_objects[current_page].present?
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
@paged_objects[current_page]
|
27
|
+
else
|
28
|
+
load_more_call.call(current_page)
|
29
|
+
end
|
30
30
|
objects = [objects].flatten.compact
|
31
31
|
@paged_objects[current_page] = objects if objects.present?
|
32
32
|
objects.each do |obj|
|
@@ -47,8 +47,8 @@ class ResponseCollection
|
|
47
47
|
@paged_objects.values.flatten
|
48
48
|
end
|
49
49
|
|
50
|
-
|
51
|
-
|
50
|
+
alias_method :size, :total
|
51
|
+
alias_method :length, :total
|
52
52
|
|
53
53
|
def empty?
|
54
54
|
total <= 0
|
data/lib/bright/school.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Bright
|
2
2
|
class School < Model
|
3
3
|
@attribute_names = [:api_id, :name, :number, :state_id, :low_grade, :high_grade, :last_modified]
|
4
|
-
attr_accessor
|
4
|
+
attr_accessor(*@attribute_names)
|
5
5
|
attr_accessor :address, :phone_number
|
6
6
|
|
7
7
|
def address=(address)
|
@@ -10,7 +10,6 @@ module Bright
|
|
10
10
|
elsif address.is_a?(Hash)
|
11
11
|
@address = Address.new(address)
|
12
12
|
end
|
13
|
-
@address
|
14
13
|
end
|
15
14
|
|
16
15
|
def phone_number=(phone_number)
|
@@ -19,8 +18,6 @@ module Bright
|
|
19
18
|
elsif phone_number.is_a?(Hash)
|
20
19
|
@phone_number = PhoneNumber.new(phone_number)
|
21
20
|
end
|
22
|
-
@phone_number
|
23
21
|
end
|
24
|
-
|
25
22
|
end
|
26
23
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Bright
|
2
2
|
module SisApi
|
3
3
|
class Aeries < Base
|
4
|
-
DATE_FORMAT =
|
4
|
+
DATE_FORMAT = "%Y-%m-%dT%H:%M:%S"
|
5
5
|
|
6
6
|
@@description = "Connects to the Aeries API for accessing student information"
|
7
7
|
@@doc_url = "http://www.aeries.com/downloads/docs.1234/TechnicalSpecs/Aeries_API_Documentation.pdf"
|
@@ -18,11 +18,11 @@ module Bright
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def get_student_by_api_id(api_id)
|
21
|
-
get_students({:
|
21
|
+
get_students({api_id: api_id, limit: 1}).first
|
22
22
|
end
|
23
23
|
|
24
24
|
def get_student(params)
|
25
|
-
get_students(params.merge(:
|
25
|
+
get_students(params.merge(limit: 1)).first
|
26
26
|
end
|
27
27
|
|
28
28
|
def get_students(params)
|
@@ -43,15 +43,15 @@ module Bright
|
|
43
43
|
|
44
44
|
def get_students_by_school(school, params = {})
|
45
45
|
school_api_id = school.is_a?(School) ? school.api_id : school
|
46
|
-
if params.has_key?(:api_id)
|
47
|
-
|
46
|
+
path = if params.has_key?(:api_id)
|
47
|
+
"api/schools/#{school_api_id}/students/#{params[:api_id]}"
|
48
48
|
elsif params.has_key?(:sis_student_id)
|
49
|
-
|
49
|
+
"api/schools/#{school_api_id}/students/sn/#{params[:sis_student_id]}"
|
50
50
|
else
|
51
|
-
|
51
|
+
"api/schools/#{school_api_id}/students"
|
52
52
|
end
|
53
|
-
students_response_hash =
|
54
|
-
students_response_hash.collect{|shsh| Student.new(convert_to_student_data(shsh))}
|
53
|
+
students_response_hash = request(:get, path, map_student_search_params(params))
|
54
|
+
students_response_hash.collect { |shsh| Student.new(convert_to_student_data(shsh)) }
|
55
55
|
end
|
56
56
|
|
57
57
|
def create_student(student)
|
@@ -63,13 +63,13 @@ module Bright
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def get_schools(params = {})
|
66
|
-
schools_response_hash =
|
66
|
+
schools_response_hash = request(:get, "api/v2/schools", params)
|
67
67
|
|
68
|
-
schools_response_hash.collect{|h| School.new(convert_to_school_data(h))}
|
68
|
+
schools_response_hash.collect { |h| School.new(convert_to_school_data(h)) }
|
69
69
|
end
|
70
70
|
|
71
71
|
def request(method, path, params = {})
|
72
|
-
uri
|
72
|
+
uri = "#{connection_options[:uri]}/#{path}"
|
73
73
|
body = nil
|
74
74
|
if method == :get
|
75
75
|
query = URI.encode_www_form(params)
|
@@ -80,7 +80,7 @@ module Bright
|
|
80
80
|
|
81
81
|
response = connection_retry_wrapper {
|
82
82
|
connection = Bright::Connection.new(uri)
|
83
|
-
headers =
|
83
|
+
headers = headers_for_auth
|
84
84
|
connection.request(method, body, headers)
|
85
85
|
}
|
86
86
|
|
@@ -119,9 +119,9 @@ module Bright
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
#SchoolCode
|
122
|
+
# SchoolCode
|
123
123
|
|
124
|
-
cattrs.reject{|k,v| v.respond_to?(:empty?) ? v.empty? : v.nil?}
|
124
|
+
cattrs.reject { |k, v| v.respond_to?(:empty?) ? v.empty? : v.nil? }
|
125
125
|
end
|
126
126
|
|
127
127
|
def convert_to_school_data(attrs)
|
@@ -131,16 +131,15 @@ module Bright
|
|
131
131
|
cattrs[:name] = attrs["Name"]
|
132
132
|
cattrs[:number] = attrs["SchoolCode"]
|
133
133
|
|
134
|
-
cattrs.reject{|k,v| v.respond_to?(:empty?) ? v.empty? : v.nil?}
|
134
|
+
cattrs.reject { |k, v| v.respond_to?(:empty?) ? v.empty? : v.nil? }
|
135
135
|
end
|
136
136
|
|
137
137
|
def headers_for_auth
|
138
138
|
{
|
139
|
-
|
140
|
-
|
139
|
+
"AERIES-CERT" => connection_options[:certificate],
|
140
|
+
"Content-Type" => "application/json"
|
141
141
|
}
|
142
142
|
end
|
143
|
-
|
144
143
|
end
|
145
144
|
end
|
146
145
|
end
|
data/lib/bright/sis_apis/base.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
module Bright
|
2
2
|
module SisApi
|
3
3
|
class Base
|
4
|
-
|
5
4
|
def filter_students_by_params(students, params)
|
6
5
|
total = params[:limit]
|
7
6
|
count = 0
|
@@ -12,7 +11,7 @@ module Bright
|
|
12
11
|
students.each do |student|
|
13
12
|
break if total and count >= total
|
14
13
|
|
15
|
-
should =
|
14
|
+
should = keys.all? do |m|
|
16
15
|
student.send(m) =~ Regexp.new(Regexp.escape(params[m]), Regexp::IGNORECASE)
|
17
16
|
end
|
18
17
|
count += 1 if total and should
|
@@ -29,7 +28,7 @@ module Bright
|
|
29
28
|
rescue Bright::ResponseError => e
|
30
29
|
retries += 1
|
31
30
|
if e.server_error? && retries <= retry_attempts.to_i
|
32
|
-
puts "retrying #{retries}: #{e.class
|
31
|
+
puts "retrying #{retries}: #{e.class} - #{e}"
|
33
32
|
sleep(retries * 3)
|
34
33
|
retry
|
35
34
|
else
|
@@ -38,7 +37,7 @@ module Bright
|
|
38
37
|
rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Net::ReadTimeout, Net::OpenTimeout, SocketError, EOFError => e
|
39
38
|
retries += 1
|
40
39
|
if retries <= retry_attempts.to_i
|
41
|
-
puts "retrying #{retries}: #{e.class
|
40
|
+
puts "retrying #{retries}: #{e.class} - #{e}"
|
42
41
|
sleep(retries * 3)
|
43
42
|
retry
|
44
43
|
else
|
@@ -46,7 +45,6 @@ module Bright
|
|
46
45
|
end
|
47
46
|
end
|
48
47
|
end
|
49
|
-
|
50
48
|
end
|
51
49
|
end
|
52
50
|
end
|