shelby-arena-api 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|