stbaldricks 1.5.1.pre

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 (117) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/lib/stbaldricks.rb +2 -0
  4. data/lib/stbaldricks/api.rb +7 -0
  5. data/lib/stbaldricks/api_connector.rb +47 -0
  6. data/lib/stbaldricks/client.rb +7 -0
  7. data/lib/stbaldricks/configuration.rb +47 -0
  8. data/lib/stbaldricks/default_logger.rb +24 -0
  9. data/lib/stbaldricks/endpoints/communicate.rb +67 -0
  10. data/lib/stbaldricks/endpoints/config.rb +18 -0
  11. data/lib/stbaldricks/endpoints/contact.rb +12 -0
  12. data/lib/stbaldricks/endpoints/event.rb +39 -0
  13. data/lib/stbaldricks/endpoints/event_application.rb +32 -0
  14. data/lib/stbaldricks/endpoints/fund.rb +24 -0
  15. data/lib/stbaldricks/endpoints/kid.rb +24 -0
  16. data/lib/stbaldricks/endpoints/kid_honor.rb +17 -0
  17. data/lib/stbaldricks/endpoints/lib/entity.rb +247 -0
  18. data/lib/stbaldricks/endpoints/message.rb +27 -0
  19. data/lib/stbaldricks/endpoints/newsletter_recipient.rb +41 -0
  20. data/lib/stbaldricks/endpoints/participant.rb +66 -0
  21. data/lib/stbaldricks/endpoints/photo.rb +51 -0
  22. data/lib/stbaldricks/endpoints/recurring_gift.rb +18 -0
  23. data/lib/stbaldricks/endpoints/search.rb +63 -0
  24. data/lib/stbaldricks/endpoints/shave_schedule.rb +28 -0
  25. data/lib/stbaldricks/endpoints/user.rb +106 -0
  26. data/lib/stbaldricks/entities/batch.rb +29 -0
  27. data/lib/stbaldricks/entities/campaign.rb +37 -0
  28. data/lib/stbaldricks/entities/communicate.rb +20 -0
  29. data/lib/stbaldricks/entities/config.rb +41 -0
  30. data/lib/stbaldricks/entities/contact.rb +40 -0
  31. data/lib/stbaldricks/entities/contact_group.rb +29 -0
  32. data/lib/stbaldricks/entities/document_library.rb +19 -0
  33. data/lib/stbaldricks/entities/document_library_category.rb +14 -0
  34. data/lib/stbaldricks/entities/donation.rb +372 -0
  35. data/lib/stbaldricks/entities/donation/donor_type.rb +13 -0
  36. data/lib/stbaldricks/entities/donation/how_created.rb +22 -0
  37. data/lib/stbaldricks/entities/donation/payment_type.rb +17 -0
  38. data/lib/stbaldricks/entities/donation/promo_code.rb +22 -0
  39. data/lib/stbaldricks/entities/donation/recipient_type.rb +17 -0
  40. data/lib/stbaldricks/entities/donation/special_donation_type.rb +78 -0
  41. data/lib/stbaldricks/entities/donation/status.rb +12 -0
  42. data/lib/stbaldricks/entities/donation/submitter_type.rb +13 -0
  43. data/lib/stbaldricks/entities/donor.rb +15 -0
  44. data/lib/stbaldricks/entities/event.rb +173 -0
  45. data/lib/stbaldricks/entities/event/fund_relationship_type.rb +15 -0
  46. data/lib/stbaldricks/entities/event/how_created.rb +14 -0
  47. data/lib/stbaldricks/entities/event/promo_code.rb +11 -0
  48. data/lib/stbaldricks/entities/event/status.rb +13 -0
  49. data/lib/stbaldricks/entities/event/sub_type.rb +16 -0
  50. data/lib/stbaldricks/entities/event/type.rb +12 -0
  51. data/lib/stbaldricks/entities/event_application.rb +135 -0
  52. data/lib/stbaldricks/entities/event_application/model_type.rb +15 -0
  53. data/lib/stbaldricks/entities/event_application/status.rb +23 -0
  54. data/lib/stbaldricks/entities/event_donation_summary.rb +18 -0
  55. data/lib/stbaldricks/entities/event_participant_summary.rb +17 -0
  56. data/lib/stbaldricks/entities/event_supporter.rb +24 -0
  57. data/lib/stbaldricks/entities/fund.rb +98 -0
  58. data/lib/stbaldricks/entities/fundraiser.rb +124 -0
  59. data/lib/stbaldricks/entities/international_partner.rb +58 -0
  60. data/lib/stbaldricks/entities/kid.rb +190 -0
  61. data/lib/stbaldricks/entities/kid_honor.rb +123 -0
  62. data/lib/stbaldricks/entities/lib/address.rb +25 -0
  63. data/lib/stbaldricks/entities/lib/base.rb +505 -0
  64. data/lib/stbaldricks/entities/lib/cacheable.rb +43 -0
  65. data/lib/stbaldricks/entities/lib/default_cacheable.rb +17 -0
  66. data/lib/stbaldricks/entities/lib/email_address.rb +15 -0
  67. data/lib/stbaldricks/entities/lib/error.rb +38 -0
  68. data/lib/stbaldricks/entities/lib/fundraising_page.rb +20 -0
  69. data/lib/stbaldricks/entities/lib/geo_location.rb +9 -0
  70. data/lib/stbaldricks/entities/lib/location.rb +27 -0
  71. data/lib/stbaldricks/entities/lib/name.rb +17 -0
  72. data/lib/stbaldricks/entities/lib/not_implemented_object.rb +32 -0
  73. data/lib/stbaldricks/entities/lib/opt_out_settings.rb +21 -0
  74. data/lib/stbaldricks/entities/lib/payment.rb +86 -0
  75. data/lib/stbaldricks/entities/lib/permissions.rb +33 -0
  76. data/lib/stbaldricks/entities/lib/phone.rb +29 -0
  77. data/lib/stbaldricks/entities/lib/third_party_media.rb +20 -0
  78. data/lib/stbaldricks/entities/lib/top_level.rb +99 -0
  79. data/lib/stbaldricks/entities/lib/venue.rb +18 -0
  80. data/lib/stbaldricks/entities/memorial.rb +61 -0
  81. data/lib/stbaldricks/entities/message.rb +65 -0
  82. data/lib/stbaldricks/entities/newsletter_recipient.rb +17 -0
  83. data/lib/stbaldricks/entities/organization.rb +90 -0
  84. data/lib/stbaldricks/entities/page.rb +49 -0
  85. data/lib/stbaldricks/entities/participant.rb +216 -0
  86. data/lib/stbaldricks/entities/person.rb +403 -0
  87. data/lib/stbaldricks/entities/photo.rb +260 -0
  88. data/lib/stbaldricks/entities/recurring_gift.rb +215 -0
  89. data/lib/stbaldricks/entities/response.rb +37 -0
  90. data/lib/stbaldricks/entities/search.rb +223 -0
  91. data/lib/stbaldricks/entities/section.rb +15 -0
  92. data/lib/stbaldricks/entities/shave_schedule.rb +69 -0
  93. data/lib/stbaldricks/entities/summary.rb +32 -0
  94. data/lib/stbaldricks/entities/team.rb +95 -0
  95. data/lib/stbaldricks/entities/user.rb +76 -0
  96. data/lib/stbaldricks/enums/country.rb +223 -0
  97. data/lib/stbaldricks/enums/feature.rb +29 -0
  98. data/lib/stbaldricks/enums/league_status.rb +16 -0
  99. data/lib/stbaldricks/enums/model_type.rb +39 -0
  100. data/lib/stbaldricks/enums/permission.rb +223 -0
  101. data/lib/stbaldricks/enums/permission_model_type.rb +21 -0
  102. data/lib/stbaldricks/enums/province.rb +39 -0
  103. data/lib/stbaldricks/enums/state.rb +137 -0
  104. data/lib/stbaldricks/enums/top_level_category_type.rb +25 -0
  105. data/lib/stbaldricks/errors.rb +18 -0
  106. data/lib/stbaldricks/log.rb +16 -0
  107. data/lib/stbaldricks/patches/array.rb +6 -0
  108. data/lib/stbaldricks/patches/boolean.rb +25 -0
  109. data/lib/stbaldricks/patches/class.rb +13 -0
  110. data/lib/stbaldricks/patches/float.rb +9 -0
  111. data/lib/stbaldricks/patches/hash.rb +16 -0
  112. data/lib/stbaldricks/patches/integer.rb +9 -0
  113. data/lib/stbaldricks/patches/nil.rb +25 -0
  114. data/lib/stbaldricks/patches/string.rb +54 -0
  115. data/lib/stbaldricks/request.rb +146 -0
  116. data/lib/stbaldricks/version.rb +5 -0
  117. metadata +215 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 89031d9008272a99db9a47cb356428979b58b64e
4
+ data.tar.gz: 50d2a0da749db09d23d977eb0a6ba021ae2a2c75
5
+ SHA512:
6
+ metadata.gz: 8d993165175669738d5e83af5a114af6401b4e77789184b1c0e6bb1c119ea7d5ee269b974b355657b93edf7821caa697842f17baae823af151898928dc4e7aaf
7
+ data.tar.gz: 5cc7a1ad9ef8a1982aed71cf21e1bbbd101201406fb6ba60c1f96f73f4677a632149e36d3ca4cb252a9728f891cfe629a0b9904b74ca5f2fd7db7120de5f0ff8
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 St. Baldrick's Foundation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift File.realpath(File.dirname(__FILE__))
2
+ require 'stbaldricks/request'
@@ -0,0 +1,7 @@
1
+ module SBF
2
+ module Client
3
+ module Api
4
+ VERSION = 'v2'.freeze
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,47 @@
1
+ module SBF
2
+ module APIConnector
3
+ # Executes API request with attempts to auto login the configured user on the API.
4
+ def with_auto_connect
5
+ # Check if we still need to attempt the initial login
6
+ if SBF::Client::Configuration.user_token.nil?
7
+ login_response = SBF::Client::User.login!(SBF::APIConnector::Configuration.username, SBF::APIConnector::Configuration.password)
8
+ error login_response.http_code, login_response.error.to_json if login_response.error?
9
+ end
10
+
11
+ # Yield to the block to execute the request
12
+ response = yield
13
+
14
+ if response.error? && response.http_code == 401
15
+ # If the user token is expired, try to login and refresh the token and try again
16
+ SBF::Client::LOG.debug { 'User session has expired attempting re-login.' }
17
+ login_response = SBF::Client::User.login!(SBF::APIConnector::Configuration.username, SBF::APIConnector::Configuration.password)
18
+ error login_response.http_code, login_response.error.to_json if login_response.error?
19
+
20
+ # Try request again
21
+ response = yield
22
+ end
23
+
24
+ response
25
+ end
26
+
27
+ class Configuration
28
+ class << self
29
+ attr_writer :username, :password
30
+ end
31
+
32
+ def self.username
33
+ @username || raise(SBF::APIConnector::Configuration::Error.new('username', 'must be set'))
34
+ end
35
+
36
+ def self.password
37
+ @password || raise(SBF::APIConnector::Configuration::Error.new('password', 'must be set'))
38
+ end
39
+
40
+ class Error < ::StandardError
41
+ def initialize(setting, message) # :nodoc:
42
+ super "SBF::APIConnector::Configuration.#{setting} #{message}"
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,7 @@
1
+ module SBF
2
+ module Client
3
+ def self.use_relative_model_naming?
4
+ true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,47 @@
1
+ require 'stbaldricks/log'
2
+ require 'logger'
3
+ require 'stbaldricks/default_logger'
4
+ require 'securerandom'
5
+
6
+ module SBF
7
+ module Client
8
+ class Configuration
9
+ DEFAULT_API_ENDPOINT = 'http://api:443'
10
+
11
+ @_logger = nil
12
+
13
+ class << self
14
+ attr_writer :base_uri, :user_token, :general_token, :request_id
15
+ attr_accessor :user_token
16
+ end
17
+
18
+ def self.base_uri
19
+ @base_uri ||= ENV['API_ENDPOINT'] || DEFAULT_API_ENDPOINT
20
+ end
21
+
22
+ def self.general_token
23
+ @general_token ||= ENV['API_KEY'] || raise(SBF::Client::Configuration::Error.new('general_token', 'must be set'))
24
+ end
25
+
26
+ def self.request_id
27
+ @request_id ||= SecureRandom.uuid
28
+ end
29
+
30
+ def self.logger=(new_logger)
31
+ missing_methods = SBF::Client::LOG::REQUIRED_METHODS.select { |method| !new_logger.respond_to?(method) }
32
+ raise SBF::Client::Configuration::Error.new('logger', "must respond to: #{missing_methods.join(', ')}") unless missing_methods.empty?
33
+ @_logger = new_logger
34
+ end
35
+
36
+ def self.logger
37
+ @_logger ||= SBF::Client::DefaultLogger.instance
38
+ end
39
+
40
+ class Error < ::StandardError
41
+ def initialize(setting, message) # :nodoc:
42
+ super "SBF::Client::Configuration.#{setting} #{message}"
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,24 @@
1
+ require 'logger'
2
+
3
+ module SBF
4
+ module Client
5
+ module DefaultLogger
6
+ def self.instance(default_stream = STDOUT)
7
+ formatter = proc { |severity, datetime, _, msg|
8
+ # ruby logger docs suggested this method for escaping messages since messages may contain user input
9
+ # and are not escaped by default.
10
+ #
11
+ # I am allowing newlines, however, for formatting purposes
12
+ "\n#{datetime}: #{severity} - #{msg.to_s.dump.gsub('\\n', "\n")}\n"
13
+ }
14
+
15
+ logger = ::Logger.new(default_stream)
16
+
17
+ logger.formatter = formatter
18
+ logger.level = ::Logger::DEBUG
19
+ logger.level = ENV['SBF_CLIENT_LOG_LEVEL'] || ::Logger::DEBUG
20
+ logger
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,67 @@
1
+ require 'stbaldricks/endpoints/lib/entity'
2
+
3
+ module SBF
4
+ module Client
5
+ class CommunicateEndpoint < SBF::Client::EntityEndpoint
6
+ def categories(_ = nil)
7
+ response = SBF::Client::Api::Request.post_request("#{base_uri}/categories")
8
+ parsed_response_body = JSON.parse(response.body).symbolize!
9
+
10
+ handle_parsed_response(parsed_response_body, response)
11
+ end
12
+
13
+ def years(category)
14
+ response = SBF::Client::Api::Request.post_request("#{base_uri}/years", category: category)
15
+ parsed_response_body = JSON.parse(response.body).symbolize!
16
+
17
+ handle_parsed_response(parsed_response_body, response)
18
+ end
19
+
20
+ def groups(category, year)
21
+ response = SBF::Client::Api::Request.post_request("#{base_uri}/groups", category: category, year: year)
22
+ parsed_response_body = JSON.parse(response.body).symbolize!
23
+
24
+ handle_parsed_response(parsed_response_body, response)
25
+ end
26
+
27
+ def compose(entity, with = {})
28
+ raise SBF::Client::Error, 'Invalid Entity' unless entity.is_a?(SBF::Client::BaseEntity)
29
+
30
+ with = normalize_with(with)
31
+
32
+ create_data = entity.to_hash
33
+ create_data.store(:with, with)
34
+
35
+ response = SBF::Client::Api::Request.post_request("#{base_uri}/compose", create_data)
36
+
37
+ error = SBF::Client::ErrorEntity.new(response.body) unless ok?(response)
38
+
39
+ SBF::Client::Api::Response.new(http_code: response.code, data: nil, error: error)
40
+ end
41
+
42
+ def contacts(category, year, group_type, group_id)
43
+ response = SBF::Client::Api::Request.post_request(
44
+ "#{base_uri}/contacts",
45
+ category: category,
46
+ year: year,
47
+ group_type: group_type,
48
+ group_id: group_id
49
+ )
50
+ parsed_response_body = JSON.parse(response.body).symbolize!
51
+ parsed_response_body.map! { |c| SBF::Client::Contact.new(c) } if ok?(response)
52
+
53
+ handle_parsed_response(parsed_response_body, response)
54
+ end
55
+
56
+ def handle_parsed_response(data, response)
57
+ unless ok?(response)
58
+ error = SBF::Client::ErrorEntity.new(data)
59
+ data = nil
60
+ end
61
+
62
+ SBF::Client::Api::Response.new(http_code: response.code, data: data, error: error)
63
+ end
64
+ private :handle_parsed_response
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,18 @@
1
+ require 'stbaldricks/endpoints/lib/entity'
2
+ require 'stbaldricks/request'
3
+
4
+ module SBF
5
+ module Client
6
+ class ConfigEndpoint < SBF::Client::EntityEndpoint
7
+ def reload(entity)
8
+ response = SBF::Client::Api::Request.public_get_request("#{base_uri}/get")
9
+ parsed_response_body = JSON.parse(response.body).symbolize!
10
+
11
+ raise SBF::Client::StandardError, 'Unable to retrieve settings from the api' unless ok?(response)
12
+
13
+ # re-call initalize with the new api data. This should re-set all of the instance variables on the instance
14
+ entity.send(:initialize, parsed_response_body)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ require 'stbaldricks/api'
2
+ require 'stbaldricks/endpoints/lib/entity'
3
+
4
+ module SBF
5
+ module Client
6
+ class ContactEndpoint < SBF::Client::EntityEndpoint
7
+ def base_uri
8
+ "/#{SBF::Client::Api::VERSION}/contact"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,39 @@
1
+ require 'stbaldricks/endpoints/lib/entity'
2
+
3
+ module SBF
4
+ module Client
5
+ class EventEndpoint < SBF::Client::EntityEndpoint
6
+ def get(id, year, with = {})
7
+ super("#{id}/#{year}", with)
8
+ end
9
+
10
+ def save(entity_or_hash, with = {})
11
+ if entity_or_hash.is_a?(SBF::Client::BaseEntity)
12
+ return create(entity_or_hash, with) if entity_or_hash.id.nil?
13
+ return update(entity_or_hash.id, entity_or_hash.year, entity_or_hash, with)
14
+ else
15
+ return create(entity_or_hash, with) if entity_or_hash[:id].nil?
16
+ return update(entity_or_hash[:id], entity_or_hash[:year], entity_or_hash, with)
17
+ end
18
+ end
19
+
20
+ def update(id, year, data, with = {})
21
+ super("#{id}/#{year}", data, with)
22
+ end
23
+
24
+ def invite(id, year, participant_data)
25
+ event_data = {id: id, year: year}
26
+ participant_data.store(:event, event_data)
27
+
28
+ response = SBF::Client::Api::Request.post_request("#{base_uri}/invite", participant_data)
29
+
30
+ unless ok?(response)
31
+ parsed_response_body = JSON.parse(response.body).symbolize!
32
+ error = SBF::Client::ErrorEntity.new(parsed_response_body)
33
+ end
34
+
35
+ SBF::Client::Api::Response.new(http_code: response.code, data: nil, error: error)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,32 @@
1
+ require 'stbaldricks/endpoints/lib/entity'
2
+
3
+ module SBF
4
+ module Client
5
+ class EventApplicationEndpoint < SBF::Client::EntityEndpoint
6
+ def create(entity, with = {})
7
+ raise SBF::Client::Error, 'Invalid Entity' unless entity.is_a?(SBF::Client::BaseEntity)
8
+
9
+ with = normalize_with(with)
10
+
11
+ create_data = entity.to_hash
12
+ create_data.store(:with, with)
13
+
14
+ entity.errors.clear
15
+
16
+ response = SBF::Client::Api::Request.public_post_request("#{base_uri}/create", create_data)
17
+ parsed_response_body = JSON.parse(response.body).symbolize!
18
+
19
+ if ok?(response)
20
+ # Re-initialize the entity using the existing data as a base and overwriting with all data returned from the response
21
+ # This will populate fields that have been auto-populated (e.g. id) into the original object
22
+ entity.attributes = create_data.merge(parsed_response_body)
23
+ else
24
+ error = SBF::Client::ErrorEntity.new(parsed_response_body)
25
+ entity.add_errors(error)
26
+ end
27
+
28
+ SBF::Client::Api::Response.new(http_code: response.code, data: entity, error: error)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ require 'stbaldricks/endpoints/lib/entity'
2
+
3
+ module SBF
4
+ module Client
5
+ class FundEndpoint < EntityEndpoint
6
+ def allowed_entities(params)
7
+ response = SBF::Client::Api::Request.post_request("#{base_uri}/allowed_entities", params)
8
+ parsed_response_body = JSON.parse(response.body).symbolize!
9
+
10
+ if ok?(response)
11
+ data = parsed_response_body
12
+ model_type = SBF::Client::ModelType.list[params[:dest_model_type]].capitalize
13
+ entity_class = "SBF::Client::Full#{model_type}".to_class
14
+ data[:results].map! { |entity| entity_class.new(entity) }
15
+ else
16
+ error = SBF::Client::ErrorEntity.new(parsed_response_body)
17
+ data = nil
18
+ end
19
+
20
+ SBF::Client::Api::Response.new(http_code: response.code, data: data, error: error)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'stbaldricks/endpoints/lib/entity'
2
+
3
+ module SBF
4
+ module Client
5
+ class KidEndpoint < SBF::Client::EntityEndpoint
6
+ def find_random(filter = [], limit = 20, with = {})
7
+ filter = filter.to_json unless filter.is_a? String
8
+ with = normalize_with(with)
9
+
10
+ response = SBF::Client::Api::Request.get_request("#{base_uri}/find_random", filter: filter, limit: limit, with: with)
11
+ parsed_response_body = JSON.parse(response.body).symbolize!
12
+
13
+ if ok?(response)
14
+ parsed_response_body[:results].map! { |entity_data| target_class.new(entity_data) }
15
+ data = parsed_response_body
16
+ else
17
+ error = SBF::Client::ErrorEntity.new(parsed_response_body)
18
+ end
19
+
20
+ SBF::Client::Api::Response.new(http_code: response.code, data: data, error: error)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ require 'stbaldricks/endpoints/lib/entity'
2
+
3
+ module SBF
4
+ module Client
5
+ class KidHonorEndpoint < EntityEndpoint
6
+ def delete(params)
7
+ response = SBF::Client::Api::Request.post_request("#{base_uri}/delete", params)
8
+
9
+ unless ok?(response)
10
+ error = SBF::Client::ErrorEntity.new(JSON.parse(response.body).symbolize!)
11
+ end
12
+
13
+ SBF::Client::Api::Response.new(http_code: response.code, data: nil, error: error)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,247 @@
1
+ require 'stbaldricks/version'
2
+ require 'stbaldricks/api'
3
+ require 'stbaldricks/entities/lib/error'
4
+ require 'stbaldricks/entities/response'
5
+ require 'stbaldricks/patches/hash'
6
+ require 'stbaldricks/patches/array'
7
+ require 'json'
8
+
9
+ module SBF
10
+ module Client
11
+ class EntityEndpoint
12
+ attr_reader :orig_target_class
13
+ attr_reader :base_uri
14
+
15
+ def initialize(target_class)
16
+ @orig_target_class = target_class
17
+ end
18
+
19
+ # Calls create if the id field is empty. Otherwise it calls update.
20
+ def save(entity_or_hash, with = {})
21
+ if entity_or_hash.is_a?(SBF::Client::BaseEntity)
22
+ return create(entity_or_hash, with) if entity_or_hash.id.nil?
23
+ return update(entity_or_hash.id, entity_or_hash, with)
24
+ else
25
+ return create(entity_or_hash, with) if entity_or_hash[:id].nil?
26
+ return update(entity_or_hash[:id], entity_or_hash, with)
27
+ end
28
+ end
29
+
30
+ # Calls the create route for the entity. Uses the class name to generate the uri
31
+ # @param with [Hash] The optional entity fields to include in the response
32
+ # @return entity [SBF::Client::BaseEntity]
33
+ def create(entity, with = {})
34
+ raise SBF::Client::Error, 'Invalid Entity' unless entity.is_a?(SBF::Client::BaseEntity)
35
+
36
+ with = normalize_with(with, entity)
37
+ create_data = entity.to_hash
38
+ create_data.store(:with, with)
39
+
40
+ response = SBF::Client::Api::Request.post_request("#{base_uri}/create", create_data)
41
+
42
+ entity, error = hydrate_entity(response, create_data, entity)
43
+
44
+ SBF::Client::Api::Response.new(http_code: response.code, data: entity, error: error)
45
+ end
46
+
47
+ # Calls the update route for the entity. Uses the class name to generate the uri
48
+ # @param with [Hash] The optional entity fields to include in the response
49
+ # @return entity [SBF::Client::BaseEntity]
50
+ def update(id = nil, entity_or_hash = nil, with = {})
51
+ if entity_or_hash.is_a?(SBF::Client::BaseEntity)
52
+ # If someone has passed in an entity, just convert it to a hash
53
+ data = entity_or_hash.to_hash
54
+ elsif entity_or_hash.is_a?(Hash)
55
+ # If someone has passed in a hash, make sure all of it's values match fields in the entity class
56
+ data = sanitize(entity_or_hash)
57
+ else
58
+ raise SBF::Client::Error, 'Invalid Data'
59
+ end
60
+
61
+ with = normalize_with(with, entity_or_hash)
62
+ data.store(:with, with)
63
+
64
+ uri = id ? "#{base_uri}/update/#{id}" : "#{base_uri}/update"
65
+ response = SBF::Client::Api::Request.post_request(uri, data)
66
+
67
+ data, error = hydrate_entity(response, data, entity_or_hash)
68
+
69
+ SBF::Client::Api::Response.new(http_code: response.code, data: data, error: error)
70
+ end
71
+
72
+ # Calls the get route for the entity. Uses the class name to generate the uri.
73
+ # @param id [integer]
74
+ # @return [SBF::Client::BaseEntity]
75
+ def get(id, with = {})
76
+ with = normalize_with(with)
77
+
78
+ response = SBF::Client::Api::Request.get_request("#{base_uri}/get/#{id}", with: with)
79
+
80
+ data, error = hydrate_entity(response, {}, nil)
81
+
82
+ SBF::Client::Api::Response.new(http_code: response.code, data: data, error: error)
83
+ end
84
+
85
+ # Calls the find route for the entity.
86
+ def find(filter = [], order = {}, limit = 20, offset = 0, with = {})
87
+ filter = filter.to_json unless filter.is_a? String
88
+ order = order.to_json unless order.is_a? String
89
+ with = normalize_with(with)
90
+
91
+ response = SBF::Client::Api::Request.get_request("#{base_uri}/find", filter: filter, order: order, limit: limit, offset: offset, with: with)
92
+ parsed_response_body = JSON.parse(response.body).symbolize!
93
+
94
+ if ok?(response)
95
+ parsed_response_body[:results].map! { |entity_data| target_class.new(entity_data) }
96
+ data = parsed_response_body
97
+ else
98
+ error = SBF::Client::ErrorEntity.new(parsed_response_body)
99
+ end
100
+
101
+ SBF::Client::Api::Response.new(http_code: response.code, data: data, error: error)
102
+ end
103
+
104
+ # Calls the find route for the entity.
105
+ def find_first(filter = [], order = {}, with = {})
106
+ api_response = find(filter, order, 1, 0, with)
107
+ api_response.data = api_response.data[:results].first unless api_response.error?
108
+ api_response
109
+ end
110
+
111
+ # Calls the aggregate route for the entity.
112
+ def aggregate(filter = [], aggregate = {})
113
+ filter = filter.to_json unless filter.is_a? String
114
+ aggregate = aggregate.to_json unless aggregate.is_a? String
115
+
116
+ response = SBF::Client::Api::Request.get_request("#{base_uri}/aggregate", filter: filter, aggregate: aggregate)
117
+ parsed_response_body = JSON.parse(response.body).symbolize!
118
+ if ok?(response)
119
+ data = parsed_response_body[:aggregate]
120
+ else
121
+ error = SBF::Client::ErrorEntity.new(parsed_response_body)
122
+ end
123
+
124
+ SBF::Client::Api::Response.new(http_code: response.code, data: data, error: error)
125
+ end
126
+
127
+ # Calls the delete route for the entity
128
+ def delete(id)
129
+ response = SBF::Client::Api::Request.post_request("#{base_uri}/delete/#{id}")
130
+
131
+ unless ok?(response)
132
+ error = SBF::Client::ErrorEntity.new(JSON.parse(response.body).symbolize!)
133
+ end
134
+
135
+ SBF::Client::Api::Response.new(http_code: response.code, data: nil, error: error)
136
+ end
137
+
138
+ def target_class
139
+ class_name_pieces = @orig_target_class.to_s.split('::')
140
+ full_name = (class_name_pieces[0..-2] + ['Full' + class_name_pieces.last]).join('::')
141
+ Object.const_defined?(full_name) ? Object.const_get(full_name) : @orig_target_class
142
+ end
143
+ private :target_class
144
+
145
+ def base_uri
146
+ class_name_pieces = @orig_target_class.to_s.split('::')
147
+ class_name_pieces[-1] = class_name_pieces[-1].gsub(/(Full|Partial)/, '')
148
+ "/#{SBF::Client::Api::VERSION}/#{class_name_pieces.last.snake_case}"
149
+ end
150
+ private :base_uri
151
+
152
+ def ok?(response)
153
+ response.code.to_s.start_with?('2')
154
+ end
155
+ private :ok?
156
+
157
+ # Remove all data that doesn't map to an appropriate field for the object type
158
+ def sanitize(data, entity_class = nil)
159
+ klass = entity_class || target_class
160
+
161
+ return sanitize(data, klass) if klass.attributes.empty?
162
+
163
+ {}.tap do |hsh|
164
+ data.each do |key, value|
165
+ next unless klass.attributes.include?(key)
166
+
167
+ # We need to sanitize the sub objects if the value is a sub-entity
168
+ if klass.entity_attributes.include?(key)
169
+ value = sanitize_entity(key, value, klass)
170
+ elsif klass.collection_attributes.include?(key)
171
+ value = value.map { |value_item| sanitize_entity(key, value_item, klass) }
172
+ end
173
+
174
+ hsh[key] = value
175
+ end
176
+ end
177
+ end
178
+ private :sanitize
179
+
180
+ def sanitize_entity(key, value, klass = target_class)
181
+ entity_class_selector_method = :"select_#{key}_class"
182
+ entity_class = klass.send(entity_class_selector_method, value)
183
+
184
+ return nil if entity_class == NilClass
185
+ entity_class.nil? ? value : sanitize(value, entity_class)
186
+ end
187
+ private :sanitize_entity
188
+
189
+ def reconstitute_with(entity)
190
+ return {} if entity.nil?
191
+
192
+ {}.tap do |hsh|
193
+ entity.class.optional_attributes.each do |attribute|
194
+ next if entity.not_provided_attributes.include?(attribute)
195
+
196
+ attribute_value = entity.send(attribute)
197
+ next if attribute_value.class.demodulize.start_with?('Partial')
198
+
199
+ hsh[attribute] = reconstitute_with(attribute_value)
200
+ end
201
+ end
202
+ end
203
+ private :reconstitute_with
204
+
205
+ def normalize_with(with, entity_or_hash = nil)
206
+ with ||= {}
207
+ with = {}.tap { |hsh| with.each { |key| hsh[key] = nil } } if with.is_a? Array
208
+ with = reconstitute_with(entity_or_hash).merge(with) if entity_or_hash.is_a? SBF::Client::BaseEntity
209
+ with = with.to_json unless with.is_a? String
210
+ with
211
+ end
212
+ private :normalize_with
213
+
214
+ def hydrate_entity(response, data, entity_or_hash)
215
+ parsed_response_body = JSON.parse(response.body).symbolize!
216
+
217
+ entity_or_hash.errors.clear if entity_or_hash.is_a?(SBF::Client::BaseEntity)
218
+
219
+ if ok?(response)
220
+ # Re-initialize the entity using the existing data as a base and overwriting with all data returned from the response
221
+ # This will populate fields that have been auto-populated or defaulted on the db (e.g. id) into the original object
222
+
223
+ new_data = parsed_response_body
224
+ new_data = data.merge(parsed_response_body) if data.is_a?(Hash)
225
+ data = target_class.new(new_data)
226
+
227
+ if entity_or_hash.is_a?(SBF::Client::BaseEntity)
228
+ entity_or_hash.attributes = new_data
229
+ data = entity_or_hash
230
+ end
231
+
232
+ return [data, nil]
233
+ else
234
+ data = entity_or_hash if entity_or_hash.is_a?(SBF::Client::BaseEntity)
235
+ data = nil if data == {}
236
+ data = target_class.new(entity_or_hash) if entity_or_hash.is_a?(Hash)
237
+
238
+ error = SBF::Client::ErrorEntity.new(parsed_response_body)
239
+ data.add_errors(error) if data.is_a?(SBF::Client::BaseEntity)
240
+
241
+ [data, error]
242
+ end
243
+ end
244
+ private :hydrate_entity
245
+ end
246
+ end
247
+ end