shelby-arena-api 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +79 -0
- data/README.rdoc +42 -0
- data/Rakefile +32 -0
- data/docs/ArenaAPI.pdf +0 -0
- data/lib/api/address.rb +28 -0
- data/lib/api/api_object.rb +32 -0
- data/lib/api/contribution.rb +42 -0
- data/lib/api/contribution_list.rb +49 -0
- data/lib/api/family.rb +49 -0
- data/lib/api/fund.rb +37 -0
- data/lib/api/fund_list.rb +49 -0
- data/lib/api/person.rb +79 -0
- data/lib/api/person_list.rb +53 -0
- data/lib/api/shelby_session.rb +17 -0
- data/lib/auto_load.rb +17 -0
- data/lib/common.rb +75 -0
- data/lib/exceptions.rb +5 -0
- data/lib/readers/api_reader.rb +26 -0
- data/lib/readers/contribution_list_reader.rb +28 -0
- data/lib/readers/contribution_reader.rb +19 -0
- data/lib/readers/family_reader.rb +21 -0
- data/lib/readers/fund_list_reader.rb +28 -0
- data/lib/readers/fund_reader.rb +19 -0
- data/lib/readers/person_list_reader.rb +45 -0
- data/lib/readers/person_reader.rb +21 -0
- data/lib/shelby_arena.rb +37 -0
- data/lib/writers/api_writer.rb +76 -0
- data/lib/writers/person_writer.rb +64 -0
- data/shelby_arena_api.gemspec +25 -0
- data/spec/functional/shelby_arena_spec.rb +17 -0
- data/spec/readers/api_reader_spec.rb +7 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/vcr_helper.rb +5 -0
- data/spec/writers/api_writer_spec.rb +7 -0
- metadata +115 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
module ShelbyArena
|
2
|
+
|
3
|
+
class FundList
|
4
|
+
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
# attr_reader :count, :page_number, :total_records, :additional_pages
|
8
|
+
|
9
|
+
|
10
|
+
# Constructor.
|
11
|
+
#
|
12
|
+
# @param options A hash of options for loading the list.
|
13
|
+
#
|
14
|
+
# Options:
|
15
|
+
# :reader - (optional) The Reader to use to load the data.
|
16
|
+
def initialize(options = {})
|
17
|
+
reader = options[:reader] || ShelbyArena::FundListReader.new(options)
|
18
|
+
@json_data = reader.load_data['FundListResult']['Funds']['Fund']
|
19
|
+
end
|
20
|
+
|
21
|
+
# Get the specified fund.
|
22
|
+
#
|
23
|
+
# @param index The index of the fund to get.
|
24
|
+
#
|
25
|
+
# @return Fund
|
26
|
+
def [](index)
|
27
|
+
Fund.new( @json_data[index] ) unless @json_data[index].nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
# This method is needed for Enumerable.
|
32
|
+
def each &block
|
33
|
+
@json_data.each{ |fund| yield( Fund.new(fund) )}
|
34
|
+
end
|
35
|
+
|
36
|
+
# Alias the count method
|
37
|
+
alias :size :count
|
38
|
+
|
39
|
+
|
40
|
+
# Checks if the list is empty.
|
41
|
+
#
|
42
|
+
# @return True on empty, false otherwise.
|
43
|
+
def empty?
|
44
|
+
self.count == 0 ? true : false
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/lib/api/person.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
module ShelbyArena
|
2
|
+
|
3
|
+
class Person < ApiObject
|
4
|
+
attribute :addresses, Array[Address]
|
5
|
+
attribute :campus_id, Integer
|
6
|
+
attribute :campus_name, String
|
7
|
+
attribute :family_id, Integer
|
8
|
+
attribute :family_member_role_id, Integer
|
9
|
+
attribute :family_member_role_value, String
|
10
|
+
attribute :gender, String
|
11
|
+
attribute :first_name, String
|
12
|
+
attribute :nick_name, String
|
13
|
+
attribute :last_name, String
|
14
|
+
attribute :birth_date, Date
|
15
|
+
attribute :age, Integer
|
16
|
+
attribute :home_phone, String
|
17
|
+
attribute :cell_phone, String
|
18
|
+
attribute :first_active_email, String
|
19
|
+
attribute :member_status_id, Integer
|
20
|
+
attribute :member_status_value, String
|
21
|
+
attribute :person_guid, String
|
22
|
+
attribute :person_id, Integer
|
23
|
+
attribute :person_link, String
|
24
|
+
attribute :record_status_value, String
|
25
|
+
attribute :bloblink, String
|
26
|
+
attribute :area_name, String
|
27
|
+
|
28
|
+
|
29
|
+
# Loads the user by the specified ID.
|
30
|
+
#
|
31
|
+
# @param person_id The ID of the person to load.
|
32
|
+
#
|
33
|
+
# Returns a new Person object.
|
34
|
+
def self.load_by_id(person_id)
|
35
|
+
reader = PersonReader.new(person_id)
|
36
|
+
self.new(reader)
|
37
|
+
rescue
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# Constructor.
|
43
|
+
#
|
44
|
+
# @param reader (optional) The object that has the data. This can be a PersonReader or Hash object.
|
45
|
+
# @param options (optional) Options for including more information.
|
46
|
+
def initialize(reader = nil, options = {})
|
47
|
+
@writer_object = PersonWriter
|
48
|
+
if reader.is_a?(PersonReader)
|
49
|
+
initialize_from_json_object(reader.load_data['Person'])
|
50
|
+
elsif reader.is_a?(Hash)
|
51
|
+
initialize_from_json_object(reader)
|
52
|
+
else # new empty
|
53
|
+
raise 'Not sure about this one yet'
|
54
|
+
# reader = PersonReader.new
|
55
|
+
# initialize_from_json_object(reader.load_new['person'])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# def is_head_of_household?
|
61
|
+
# # I do not see a way to get this yet.
|
62
|
+
# end
|
63
|
+
|
64
|
+
|
65
|
+
def family_role
|
66
|
+
self.family_member_role_value.blank? ? 'Other' : self.family_member_role_value
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def is_child?
|
71
|
+
self.family_member_role_value.downcase == 'child'
|
72
|
+
end
|
73
|
+
|
74
|
+
def email_address
|
75
|
+
self.first_active_email
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ShelbyArena
|
2
|
+
|
3
|
+
class PersonList
|
4
|
+
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
# Constructor.
|
8
|
+
#
|
9
|
+
# @param options A hash of options for loading the list.
|
10
|
+
#
|
11
|
+
# Options:
|
12
|
+
# :reader - (optional) The Reader to use to load the data.
|
13
|
+
def initialize(options = {})
|
14
|
+
reader = options[:reader] || ShelbyArena::PersonListReader.new(options)
|
15
|
+
@json_data = reader.load_data['PersonListResult']['Persons']['Person']
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get the specified person.
|
19
|
+
#
|
20
|
+
# @param index The index of the person to get.
|
21
|
+
#
|
22
|
+
# @return [Person]
|
23
|
+
def [](index)
|
24
|
+
Person.new( @json_data[index] ) unless @json_data[index].nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# This method is needed for Enumerable.
|
29
|
+
def each &block
|
30
|
+
@json_data.each{ |person| yield( Person.new(person) )}
|
31
|
+
end
|
32
|
+
|
33
|
+
# Alias the count method
|
34
|
+
alias :size :count
|
35
|
+
|
36
|
+
# Checks if the list is empty.
|
37
|
+
#
|
38
|
+
# @return True on empty, false otherwise.
|
39
|
+
def empty?
|
40
|
+
#@json_data['person'].empty?
|
41
|
+
self.count == 0 ? true : false
|
42
|
+
end
|
43
|
+
|
44
|
+
# Access to the raw JSON data. This method is needed for merging lists.
|
45
|
+
#
|
46
|
+
# @returns Raw JSON data.
|
47
|
+
def raw_data
|
48
|
+
@json_data
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ShelbyArena
|
2
|
+
|
3
|
+
class ShelbySession < ApiObject
|
4
|
+
attribute :id, String
|
5
|
+
attribute :expires_at, DateTime
|
6
|
+
|
7
|
+
# Constructor.
|
8
|
+
#
|
9
|
+
# @param response_data Session response data from the Shelby service.
|
10
|
+
def initialize(response_data)
|
11
|
+
self.id = response_data['ApiSession']['SessionID']
|
12
|
+
self.expires_at = response_data['ApiSession']['DateExpires']
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/lib/auto_load.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module ShelbyArena
|
2
|
+
|
3
|
+
require SHELBY_ARENA_LIB_DIR + '/exceptions.rb'
|
4
|
+
|
5
|
+
api_path = SHELBY_ARENA_LIB_DIR + '/api/'
|
6
|
+
require api_path + 'api_object.rb'
|
7
|
+
Dir["#{api_path}/*.rb"].each { |f| require(f) }
|
8
|
+
|
9
|
+
readers_path = SHELBY_ARENA_LIB_DIR + '/readers/'
|
10
|
+
require readers_path + 'api_reader.rb'
|
11
|
+
Dir["#{readers_path}/*.rb"].each { |f| require(f) }
|
12
|
+
|
13
|
+
writers_path = SHELBY_ARENA_LIB_DIR + '/writers/'
|
14
|
+
require writers_path + 'api_writer.rb'
|
15
|
+
Dir["#{writers_path}/*.rb"].each { |f| require(f) }
|
16
|
+
|
17
|
+
end
|
data/lib/common.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
module ShelbyArena
|
2
|
+
|
3
|
+
def self.request_session
|
4
|
+
response = Typhoeus::Request.post(ShelbyArena::Api.service_url+'/login', {body: {username: ShelbyArena::Api.username, password: ShelbyArena::Api.password, api_key: ShelbyArena::Api.api_key}})
|
5
|
+
raise ShelbyArenaExceptions::UnableToConnectToShelbyArena.new(response.body) unless response.success?
|
6
|
+
self._xml2json(response.body)
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
def self.api_request(method, path, params = {}, body = nil)
|
11
|
+
url = [ShelbyArena::Api.service_url, path].join('/')
|
12
|
+
mparams = params.merge({api_session: ShelbyArena::Api.session_key})
|
13
|
+
mparams = mparams.merge({api_sig: self._generate_api_signature(path, params)})
|
14
|
+
|
15
|
+
response =
|
16
|
+
case method
|
17
|
+
when :post
|
18
|
+
raise 'Shelby POST not tested yet'
|
19
|
+
#Typhoeus::Request.post(url, {:headers => headers, :body => body})
|
20
|
+
when :get
|
21
|
+
Typhoeus::Request.get(url, params: mparams)
|
22
|
+
when :put
|
23
|
+
raise 'Shelby PUT not tested yet'
|
24
|
+
# Typhoeus::Request.put(url, {:headers => headers, :body => body})
|
25
|
+
when :delete
|
26
|
+
raise 'Shelby DELETE not tested yet'
|
27
|
+
# Typhoeus::Request.delete(url, {:headers => headers, :params => params})
|
28
|
+
end
|
29
|
+
|
30
|
+
if !response.success?
|
31
|
+
if response.code > 0
|
32
|
+
raise ShelbyArenaExceptions::UnableToConnectToShelbyArena.new(response.body)
|
33
|
+
else
|
34
|
+
begin
|
35
|
+
error_messages = JSON.parse(response.body)['error_message']
|
36
|
+
rescue
|
37
|
+
response_code_desc = response.headers.partition("\r\n")[0].sub(/^\S+/, '') rescue nil
|
38
|
+
raise ShelbyArenaExceptions::UnknownErrorConnectingToShelbyArena.new("Unknown error when connecting to Shelby Arena.#{response_code_desc}")
|
39
|
+
else
|
40
|
+
raise ShelbyArenaExceptions::ShelbyArenaResponseError.new(error_messages)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
response
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def self._xml2json(xml)
|
50
|
+
# {KeepRoot: true, ForceArray: false, SuppressEmpty: true} were set to
|
51
|
+
# maximize compatibility with Hash.from_xml, used previously.
|
52
|
+
#
|
53
|
+
XmlSimple.xml_in(xml, {KeepRoot: true, ForceArray: false, SuppressEmpty: true})
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def self._generate_api_signature(path, params)
|
58
|
+
get_vars = ''
|
59
|
+
if params.to_a.size > 0
|
60
|
+
get_vars = '?' + params.to_a.sort.collect { |kv_pair| "#{kv_pair[0]}=#{kv_pair[1].to_s}" }.join('&').downcase
|
61
|
+
end
|
62
|
+
utoken = get_vars.empty? ? '?' : '&'
|
63
|
+
Digest::MD5.hexdigest("#{ShelbyArena::Api.api_secret}_#{path.downcase}#{get_vars}#{utoken}api_session=#{ShelbyArena::Api.session_key}")
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# This is a helper method
|
68
|
+
def self.attr_underscore(str)
|
69
|
+
str.gsub(/::/, '/')
|
70
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
71
|
+
.gsub(/([a-z\d])([A-Z])/,'\1_\2')
|
72
|
+
.tr("-", "_")
|
73
|
+
.downcase
|
74
|
+
end
|
75
|
+
end
|
data/lib/exceptions.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
module ShelbyArena
|
3
|
+
|
4
|
+
# This class is the base class for all ShelbyArena objects and is meant to be inherited.
|
5
|
+
class ApiReader
|
6
|
+
attr_reader :headers
|
7
|
+
|
8
|
+
# Loads the data.
|
9
|
+
#
|
10
|
+
# @return the data loaded in a JSON object.
|
11
|
+
def load_data
|
12
|
+
@url_data_params ||= {}
|
13
|
+
return _load_data(@url_data_path, @url_data_params)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def _load_data(url_data_path, url_data_params)
|
19
|
+
response = ShelbyArena::api_request(:get, url_data_path, url_data_params)
|
20
|
+
@headers = response.headers
|
21
|
+
ShelbyArena::_xml2json(response.body)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ShelbyArena
|
2
|
+
|
3
|
+
class ContributionListReader < ApiReader
|
4
|
+
|
5
|
+
# Constructor.
|
6
|
+
def initialize(options = {})
|
7
|
+
# page = options[:page] || 1
|
8
|
+
# per_page = options[:per_page] || 100
|
9
|
+
|
10
|
+
@url_data_params = {}
|
11
|
+
valid_fields.each { |field| @url_data_params[field] = options[ShelbyArena::attr_underscore(field).to_sym] unless options[ShelbyArena::attr_underscore(field).to_sym].nil? }
|
12
|
+
@url_data_path = 'contribution/list'
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_fields
|
16
|
+
%W(Active
|
17
|
+
CanPledge
|
18
|
+
EndDate
|
19
|
+
FundId
|
20
|
+
FundName
|
21
|
+
OnlineName
|
22
|
+
StartDate
|
23
|
+
TaxDeductible).sort
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ShelbyArena
|
2
|
+
|
3
|
+
class ContributionReader < ApiReader
|
4
|
+
|
5
|
+
# Constructor.
|
6
|
+
#
|
7
|
+
# @param contribution_id (optional) The ID of the contribution to load.
|
8
|
+
def initialize(contribution_id = nil)
|
9
|
+
if contribution_id.nil?
|
10
|
+
raise 'The create endpoint is not known yet.'
|
11
|
+
@url_new_data_path = nil # Not sure yet
|
12
|
+
else
|
13
|
+
@url_data_path = "contribution/#{contribution_id}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ShelbyArena
|
2
|
+
|
3
|
+
class FamilyReader < ApiReader
|
4
|
+
|
5
|
+
# Constructor.
|
6
|
+
#
|
7
|
+
# @param family_id (optional) The ID of the family to load.
|
8
|
+
def initialize(family_id = nil)
|
9
|
+
if family_id.nil?
|
10
|
+
raise 'The create endpoint is not known yet.'
|
11
|
+
@url_new_data_path = nil # Not sure yet
|
12
|
+
else
|
13
|
+
@url_data_path = "family/#{family_id}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ShelbyArena
|
2
|
+
|
3
|
+
class FundListReader < ApiReader
|
4
|
+
|
5
|
+
# Constructor.
|
6
|
+
def initialize(options = {})
|
7
|
+
# page = options[:page] || 1
|
8
|
+
# per_page = options[:per_page] || 100
|
9
|
+
|
10
|
+
@url_data_params = {}
|
11
|
+
valid_fields.each { |field| @url_data_params[field] = options[ShelbyArena::attr_underscore(field).to_sym] unless options[ShelbyArena::attr_underscore(field).to_sym].nil? }
|
12
|
+
@url_data_path = 'fund/list'
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_fields
|
16
|
+
%W(Active
|
17
|
+
CanPledge
|
18
|
+
EndDate
|
19
|
+
FundId
|
20
|
+
FundName
|
21
|
+
OnlineName
|
22
|
+
StartDate
|
23
|
+
TaxDeductible).sort
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ShelbyArena
|
2
|
+
|
3
|
+
class FundReader < ApiReader
|
4
|
+
|
5
|
+
# Constructor.
|
6
|
+
#
|
7
|
+
# @param fund_id (optional) The ID of the fund to load.
|
8
|
+
def initialize(fund_id = nil)
|
9
|
+
if fund_id.nil?
|
10
|
+
raise 'The create endpoint is not known yet.'
|
11
|
+
@url_new_data_path = nil # Not sure yet
|
12
|
+
else
|
13
|
+
@url_data_path = "fund/#{fund_id}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|