ngp_van 0.1.1

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 (95) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -0
  4. data/README.md +117 -0
  5. data/lib/ngp_van.rb +47 -0
  6. data/lib/ngp_van/client.rb +41 -0
  7. data/lib/ngp_van/client/activist_codes.rb +15 -0
  8. data/lib/ngp_van/client/canvass_responses.rb +19 -0
  9. data/lib/ngp_van/client/codes.rb +31 -0
  10. data/lib/ngp_van/client/district_fields.rb +15 -0
  11. data/lib/ngp_van/client/event_types.rb +15 -0
  12. data/lib/ngp_van/client/events.rb +31 -0
  13. data/lib/ngp_van/client/locations.rb +27 -0
  14. data/lib/ngp_van/client/minivan_exports.rb +15 -0
  15. data/lib/ngp_van/client/notes.rb +19 -0
  16. data/lib/ngp_van/client/people.rb +31 -0
  17. data/lib/ngp_van/client/printed_lists.rb +15 -0
  18. data/lib/ngp_van/client/signups.rb +31 -0
  19. data/lib/ngp_van/client/survey_questions.rb +15 -0
  20. data/lib/ngp_van/client/users.rb +19 -0
  21. data/lib/ngp_van/configuration.rb +74 -0
  22. data/lib/ngp_van/connection.rb +32 -0
  23. data/lib/ngp_van/default.rb +41 -0
  24. data/lib/ngp_van/error.rb +124 -0
  25. data/lib/ngp_van/request.rb +39 -0
  26. data/lib/ngp_van/response.rb +15 -0
  27. data/lib/ngp_van/response/raise_error.rb +17 -0
  28. data/lib/ngp_van/version.rb +19 -0
  29. data/spec/ngp_van/client/activist_codes_spec.rb +88 -0
  30. data/spec/ngp_van/client/canvass_responses_spec.rb +126 -0
  31. data/spec/ngp_van/client/codes_spec.rb +197 -0
  32. data/spec/ngp_van/client/district_fields_spec.rb +79 -0
  33. data/spec/ngp_van/client/event_types_spec.rb +69 -0
  34. data/spec/ngp_van/client/events_spec.rb +205 -0
  35. data/spec/ngp_van/client/locations_spec.rb +172 -0
  36. data/spec/ngp_van/client/minivan_exports_spec.rb +82 -0
  37. data/spec/ngp_van/client/notes_spec.rb +107 -0
  38. data/spec/ngp_van/client/people_spec.rb +227 -0
  39. data/spec/ngp_van/client/printed_lists_spec.rb +91 -0
  40. data/spec/ngp_van/client/signups_spec.rb +209 -0
  41. data/spec/ngp_van/client/survey_questions_spec.rb +83 -0
  42. data/spec/ngp_van/client/users_spec.rb +122 -0
  43. data/spec/ngp_van/configuration_spec.rb +116 -0
  44. data/spec/ngp_van/request_spec.rb +137 -0
  45. data/spec/ngp_van_spec.rb +29 -0
  46. data/spec/spec_helper.rb +11 -0
  47. data/spec/support/fixtures/activist_code.json +10 -0
  48. data/spec/support/fixtures/activist_codes.json +36 -0
  49. data/spec/support/fixtures/canvass_response.json +25 -0
  50. data/spec/support/fixtures/canvass_responses_contact_types.json +10 -0
  51. data/spec/support/fixtures/canvass_responses_input_types.json +26 -0
  52. data/spec/support/fixtures/canvass_responses_result_codes.json +26 -0
  53. data/spec/support/fixtures/code.json +18 -0
  54. data/spec/support/fixtures/code_supported_entities.json +5 -0
  55. data/spec/support/fixtures/codes.json +55 -0
  56. data/spec/support/fixtures/create_code.json +16 -0
  57. data/spec/support/fixtures/create_event.json +62 -0
  58. data/spec/support/fixtures/create_event_shift.json +5 -0
  59. data/spec/support/fixtures/create_location.json +9 -0
  60. data/spec/support/fixtures/create_signup.json +32 -0
  61. data/spec/support/fixtures/create_user_district_field_values.json +7 -0
  62. data/spec/support/fixtures/district_field.json +28 -0
  63. data/spec/support/fixtures/district_fields.json +22 -0
  64. data/spec/support/fixtures/event.json +139 -0
  65. data/spec/support/fixtures/event_type.json +75 -0
  66. data/spec/support/fixtures/event_types.json +77 -0
  67. data/spec/support/fixtures/events.json +86 -0
  68. data/spec/support/fixtures/location.json +19 -0
  69. data/spec/support/fixtures/locations.json +25 -0
  70. data/spec/support/fixtures/match_candidate.json +61 -0
  71. data/spec/support/fixtures/match_response.json +4 -0
  72. data/spec/support/fixtures/minivan_export.json +66 -0
  73. data/spec/support/fixtures/minivan_exports.json +72 -0
  74. data/spec/support/fixtures/note_categories.json +17 -0
  75. data/spec/support/fixtures/note_category.json +8 -0
  76. data/spec/support/fixtures/note_category_types.json +6 -0
  77. data/spec/support/fixtures/person.json +61 -0
  78. data/spec/support/fixtures/printed_list.json +52 -0
  79. data/spec/support/fixtures/printed_lists.json +58 -0
  80. data/spec/support/fixtures/signup.json +55 -0
  81. data/spec/support/fixtures/signup_statuses.json +26 -0
  82. data/spec/support/fixtures/signups.json +112 -0
  83. data/spec/support/fixtures/survey_question.json +36 -0
  84. data/spec/support/fixtures/survey_questions.json +85 -0
  85. data/spec/support/fixtures/update_code.json +22 -0
  86. data/spec/support/fixtures/update_event.json +61 -0
  87. data/spec/support/fixtures/update_signup.json +35 -0
  88. data/spec/support/fixtures/update_user_district_field_values.json +6 -0
  89. data/spec/support/fixtures/user_district_field_values.json +7 -0
  90. data/spec/support/path_helpers.rb +9 -0
  91. data/spec/support/rspec.rb +51 -0
  92. data/spec/support/url_helpers.rb +5 -0
  93. data/spec/support/webmock.rb +5 -0
  94. metadata +269 -0
  95. metadata.gz.sig +0 -0
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NgpVan
4
+ class Client
5
+ module PrintedLists
6
+ def printed_lists(params: {})
7
+ get(path: 'printedLists', params: params)
8
+ end
9
+
10
+ def printed_list(id:, params: {})
11
+ get(path: "printedLists/#{id}", params: params)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NgpVan
4
+ class Client
5
+ module Signups
6
+ def signup_statuses(params: {})
7
+ get(path: 'signups/statuses', params: params)
8
+ end
9
+
10
+ def signup(id:, params: {})
11
+ get(path: "signups/#{id}", params: params)
12
+ end
13
+
14
+ def signups(params: {})
15
+ get(path: 'signups', params: params)
16
+ end
17
+
18
+ def create_signup(body: {})
19
+ post(path: 'signups', body: body)
20
+ end
21
+
22
+ def update_signup(id:, body: {})
23
+ put(path: "signups/#{id}", body: body)
24
+ end
25
+
26
+ def delete_signup(id:)
27
+ delete(path: "signups/#{id}")
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NgpVan
4
+ class Client
5
+ module SurveyQuestions
6
+ def survey_questions(params: {})
7
+ get(path: 'surveyQuestions', params: params)
8
+ end
9
+
10
+ def survey_question(id:, params: {})
11
+ get(path: "surveyQuestions/#{id}", params: params)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NgpVan
4
+ class Client
5
+ module Users
6
+ def user_district_field_values(id:, params: {})
7
+ get(path: "users/#{id}/districtFieldValues", params: params)
8
+ end
9
+
10
+ def create_user_district_field_values(id:, body: {})
11
+ post(path: "users/#{id}/districtFieldValues", body: body)
12
+ end
13
+
14
+ def update_user_district_field_values(id:, body: {})
15
+ put(path: "users/#{id}/districtFieldValues", body: body)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ngp_van/default'
4
+ require 'ngp_van/version'
5
+
6
+ module NgpVan
7
+ class Configuration
8
+ # The Application Name in the NGP VAN system. A short string that identifies
9
+ # your application (e.g., acmeCrmProduct)
10
+ #
11
+ # The `application_name` setting is used for authenticating requests.
12
+ #
13
+ # @return [String, nil]
14
+ attr_accessor :application_name
15
+
16
+ # The API Key acquired from NGP VAN. The API Key resembles the concatenation
17
+ # of a GUID, a | and a 0 or 1 (e.g.,
18
+ # bc7b6578-5619-4e8f-92ab-829208e1a511|1).
19
+ #
20
+ # The `api_key` setting is used for authenticating requests.
21
+ #
22
+ # @return [String, nil]
23
+ attr_accessor :api_key
24
+
25
+ # The API Endpoint url. Which endpoint you should use is determined by which
26
+ # VAN client with which you're working.
27
+ # @note See http://developers.ngpvan.com/van-api#van-endpoints
28
+ # @return [String]
29
+ attr_accessor :api_endpoint
30
+
31
+ # The User-Agent sent to the API endpoint. This defaults to the gem name,
32
+ # suffixed with the current version number.
33
+ # @return [String]
34
+ attr_accessor :user_agent
35
+
36
+ def initialize
37
+ setup
38
+ end
39
+
40
+ # Reset all configuration to default values.
41
+ # @return [NgpVan::Configuration]
42
+ def reset!
43
+ @application_name = NgpVan::Default.application_name
44
+ @api_key = NgpVan::Default.api_key
45
+ @api_endpoint = NgpVan::Default.api_endpoint
46
+ @user_agent = NgpVan::Default.user_agent
47
+ self
48
+ end
49
+
50
+ alias setup reset!
51
+
52
+ # Inspect the configuration object, masking private values.
53
+ # @return [String]
54
+ def inspect
55
+ inspected = super
56
+
57
+ if NgpVan.configuration.api_key
58
+ filter_value!(inspected, NgpVan.configuration.api_key)
59
+ end
60
+
61
+ if NgpVan.configuration.application_name
62
+ filter_value!(inspected, NgpVan.configuration.application_name)
63
+ end
64
+
65
+ inspected
66
+ end
67
+
68
+ private
69
+
70
+ def filter_value!(source, str)
71
+ source.gsub!(str, '[FILTERED]')
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ngp_van/response/raise_error'
4
+ require 'faraday_middleware'
5
+
6
+ module NgpVan
7
+ module Connection
8
+ private
9
+
10
+ # rubocop:disable Metrics/MethodLength
11
+ def connection
12
+ options = {
13
+ url: NgpVan.configuration.api_endpoint,
14
+ headers: {
15
+ 'Accept' => 'application/json; charset=utf-8',
16
+ 'User-Agent' => NgpVan.configuration.user_agent
17
+ }
18
+ }
19
+
20
+ Faraday::Connection.new(options) do |connection|
21
+ connection.basic_auth(
22
+ NgpVan.configuration.application_name,
23
+ NgpVan.configuration.api_key
24
+ )
25
+
26
+ connection.request(:json)
27
+ connection.use NgpVan::Response::RaiseError
28
+ connection.adapter(Faraday.default_adapter)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ngp_van/version'
4
+
5
+ module NgpVan
6
+ module Default
7
+ APPLICATION_NAME = nil
8
+
9
+ API_KEY = nil
10
+
11
+ API_ENDPOINT = 'https://api.securevan.com/v4/'
12
+
13
+ USER_AGENT = "NGP VAN Ruby Gem #{NgpVan::VERSION}"
14
+
15
+ class << self
16
+ # Default Application Name from {APPLICATION_NAME}
17
+ # @return [String]
18
+ def application_name
19
+ APPLICATION_NAME
20
+ end
21
+
22
+ # Default API Key from {API_KEY}
23
+ # @return [String]
24
+ def api_key
25
+ API_KEY
26
+ end
27
+
28
+ # Default API Endpoint from {API_ENDPOINT}
29
+ # @return [String]
30
+ def api_endpoint
31
+ API_ENDPOINT
32
+ end
33
+
34
+ # Default User Agent from {USER_AGENT}
35
+ # @return [String]
36
+ def user_agent
37
+ USER_AGENT
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NgpVan
4
+ # Custom error class for rescuing from NgpVan errors.
5
+ class Error < StandardError
6
+ attr_reader :body, :response, :status
7
+
8
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize,
9
+ # rubocop:disable Style/CyclomaticComplexity
10
+ # Returns a NgpVan::Error subclass, depending on status and
11
+ # response message.
12
+ #
13
+ # @param [Hash] response HTTP response
14
+ # @return [NgpVan::Error]
15
+ def self.from_response(response)
16
+ status = response[:status].to_i
17
+
18
+ error_klass =
19
+ case status
20
+ when 400 then NgpVan::BadRequest
21
+ when 401 then NgpVan::Unauthorized
22
+ when 403 then NgpVan::Forbidden
23
+ when 405 then NgpVan::MethodNotAllowed
24
+ when 406 then NgpVan::NotAcceptable
25
+ when 408 then NgpVan::RequestTimeout
26
+ when 409 then NgpVan::Conflict
27
+ when 413 then NgpVan::RequestEntityTooLarge
28
+ when 415 then NgpVan::UnsupportedMediaType
29
+ when 422 then NgpVan::UnprocessableEntity
30
+ when 429 then NgpVan::TooManyRequests
31
+ when 404 then NgpVan::NotFound
32
+ when 400..499 then NgpVan::ClientError
33
+ when 500 then NgpVan::InternalServerError
34
+ when 501 then NgpVan::NotImplemented
35
+ when 502 then NgpVan::BadGateway
36
+ when 503 then NgpVan::ServiceUnavailable
37
+ when 504 then NgpVan::GatewayTimeout
38
+ when 500..599 then NgpVan::ServerError
39
+ end
40
+
41
+ error_klass.new(response) if error_klass
42
+ end
43
+
44
+ def initialize(response = nil)
45
+ @response = response
46
+ @body = ::JSON.parse(response[:body])
47
+ @status = response[:status]
48
+
49
+ super(build_error)
50
+ end
51
+
52
+ private
53
+
54
+ def errors
55
+ body.delete('errors')
56
+ end
57
+
58
+ def build_error
59
+ return nil if response.nil?
60
+
61
+ {
62
+ status: status,
63
+ errors: errors
64
+ }
65
+ end
66
+ end
67
+
68
+ # Errors in the 400-499 range
69
+ class ClientError < Error; end
70
+
71
+ # 400 Bad request
72
+ class BadRequest < ClientError; end
73
+
74
+ # 401 Unauthorized
75
+ class Unauthorized < ClientError; end
76
+
77
+ # 403 Forbidden
78
+ class Forbidden < ClientError; end
79
+
80
+ # 404 Not found
81
+ class NotFound < ClientError; end
82
+
83
+ # 405 Method not allowed
84
+ class MethodNotAllowed < ClientError; end
85
+
86
+ # 406 Not acceptable
87
+ class NotAcceptable < ClientError; end
88
+
89
+ # 408 Request timeout
90
+ class RequestTimeout < ClientError; end
91
+
92
+ # 409 Conflict
93
+ class Conflict < ClientError; end
94
+
95
+ # 413 Request entity too large
96
+ class RequestEntityTooLarge < ClientError; end
97
+
98
+ # 415 Unsupported media type
99
+ class UnsupportedMediaType < ClientError; end
100
+
101
+ # 422 Unprocessable entity
102
+ class UnprocessableEntity < ClientError; end
103
+
104
+ # 429 Too many requests
105
+ class TooManyRequests < ClientError; end
106
+
107
+ # Errors in the 500-599 range
108
+ class ServerError < Error; end
109
+
110
+ # 500 Internal server error
111
+ class InternalServerError < ServerError; end
112
+
113
+ # 501 Not implemented
114
+ class NotImplemented < ServerError; end
115
+
116
+ # 502 Bad gateway
117
+ class BadGateway < ServerError; end
118
+
119
+ # 503 Service unavailable
120
+ class ServiceUnavailable < ServerError; end
121
+
122
+ # 504 Gateway timeout
123
+ class GatewayTimeout < ServerError; end
124
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module NgpVan
6
+ module Request
7
+ # Perform an HTTP DELETE request
8
+ def delete(path:, params: {})
9
+ request(method: :delete, path: path, params: params)
10
+ end
11
+
12
+ # Perform an HTTP GET request
13
+ def get(path:, params: {})
14
+ request(method: :get, path: path, params: params)
15
+ end
16
+
17
+ # Perform an HTTP POST request
18
+ def post(path:, body: {})
19
+ request(method: :post, path: path, body: body)
20
+ end
21
+
22
+ # Perform an HTTP PUT request
23
+ def put(path:, body: {})
24
+ request(method: :put, path: path, body: body)
25
+ end
26
+
27
+ private
28
+
29
+ def request(method:, path:, params: {}, body: {})
30
+ response = connection.send(method) do |request|
31
+ request.path = URI.encode(path)
32
+ request.params = params
33
+ request.body = ::JSON.generate(body) unless body.empty?
34
+ end
35
+
36
+ Response.create(response.body)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NgpVan
4
+ module Response
5
+ def self.create(body)
6
+ JSON.parse(body)
7
+ # The VAN API does not always return JSON. For example, when creating a new
8
+ # code, you post to /codes. The return is the integer ID of the newly
9
+ # created code, not a json representation of it. For cases like this, we
10
+ # will just return the body un-parsed.
11
+ rescue JSON::ParserError
12
+ body
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ngp_van/error'
4
+ require 'faraday'
5
+
6
+ module NgpVan
7
+ module Response
8
+ class RaiseError < Faraday::Response::Middleware
9
+ private
10
+
11
+ def on_complete(response)
12
+ error = NgpVan::Error.from_response(response)
13
+ raise error if error
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NgpVan
4
+ # Current major release.
5
+ # @return [Integer]
6
+ MAJOR = 0
7
+
8
+ # Current minor release.
9
+ # @return [Integer]
10
+ MINOR = 1
11
+
12
+ # Current patch level.
13
+ # @return [Integer]
14
+ PATCH = 1
15
+
16
+ # Full release version.
17
+ # @return [String]
18
+ VERSION = [MAJOR, MINOR, PATCH].join('.').freeze
19
+ end