unit-ruby 0.1.0 → 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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +32 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +1 -1
- data/LICENSE.txt +1 -1
- data/bin/console +1 -1
- data/lib/unit-ruby/application_form.rb +8 -4
- data/lib/unit-ruby/atm_location.rb +2 -2
- data/lib/unit-ruby/deposit_account.rb +5 -5
- data/lib/unit-ruby/individual_application.rb +27 -27
- data/lib/unit-ruby/individual_customer.rb +5 -5
- data/lib/unit-ruby/individual_debit_card.rb +5 -5
- data/lib/unit-ruby/institution.rb +2 -2
- data/lib/unit-ruby/transaction.rb +13 -0
- data/lib/unit-ruby/types/application_form_settings_override.rb +1 -1
- data/lib/unit-ruby/types/date.rb +2 -0
- data/lib/unit-ruby/types/date_time.rb +1 -1
- data/lib/unit-ruby/util/api_resource.rb +130 -129
- data/lib/unit-ruby/util/connection.rb +50 -52
- data/lib/unit-ruby/util/error.rb +8 -10
- data/lib/unit-ruby/util/resource_operations.rb +56 -58
- data/lib/unit-ruby/util/schema.rb +12 -10
- data/lib/unit-ruby/version.rb +1 -1
- data/lib/unit-ruby.rb +2 -2
- data/unit-ruby.gemspec +2 -2
- metadata +7 -3
- data/lib/unit-ruby/types/decimal.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59f7e21224f067de8f06a1a569279ce2d3a6d242f44725c10d44f9d723627a4a
|
4
|
+
data.tar.gz: 58a09d8c0de08370dc789d15968893acfcfa449d0aa0d1f9acb7d2c1f0c84fce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7bdca7d29ac184aaa4fa095bd9f5f1f4e4e027a8d889a608e4d3f11dbfd53991ab9f17f198a8a29c4f212ce17a2903015ae8183f7580c5463e7e331cd238d492
|
7
|
+
data.tar.gz: '0782d46df4e8cfdf9659945939fb40fbb7e8f5d5cfc965745e88b1d2249b18e8230efcb80079e559f97670bb46341bc533b0abc4f21bac76818ba1737062a398'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Ruby
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [ main ]
|
13
|
+
pull_request:
|
14
|
+
branches: [ main ]
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
test:
|
18
|
+
|
19
|
+
runs-on: ubuntu-latest
|
20
|
+
strategy:
|
21
|
+
matrix:
|
22
|
+
ruby-version: ['2.6', '2.7', '3.0']
|
23
|
+
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v2
|
26
|
+
- name: Set up Ruby
|
27
|
+
uses: ruby/setup-ruby@v1
|
28
|
+
with:
|
29
|
+
ruby-version: ${{ matrix.ruby-version }}
|
30
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
31
|
+
- name: Run tests
|
32
|
+
run: bundle exec rake
|
data/Gemfile.lock
CHANGED
data/LICENSE.txt
CHANGED
data/bin/console
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
module Unit
|
2
|
-
class ApplicationForm <
|
2
|
+
class ApplicationForm < APIResource
|
3
3
|
path '/application-forms'
|
4
4
|
|
5
5
|
attribute :tags, Types::Hash # Optional
|
6
6
|
attribute :allowed_application_types, Types::Array # Optional. Array of Individual, Business or SoleProprietorship.
|
7
7
|
attribute :applicant_details, Types::ApplicationFormPrefill # Optional. Add data that is already known about the end-customer to be auto populated on the form.
|
8
8
|
attribute :settings_override, Types::ApplicationFormSettingsOverride # Optional. Override disclosure URLs that were defined in the application form settings.
|
9
|
-
attribute :stage, Types::String
|
10
|
-
attribute :url, Types::String
|
11
9
|
|
12
|
-
|
10
|
+
attribute :stage, Types::String, readonly: true
|
11
|
+
attribute :url, Types::String, readonly: true
|
12
|
+
|
13
|
+
belongs_to :application, class_name: 'Unit::IndividualApplication'
|
14
|
+
|
15
|
+
include ResourceOperations::Create
|
16
|
+
include ResourceOperations::Find
|
13
17
|
end
|
14
18
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Unit
|
2
|
-
class AtmLocation <
|
2
|
+
class AtmLocation < APIResource
|
3
3
|
path '/atm-locations'
|
4
4
|
attribute :network, Types::String
|
5
5
|
attribute :address, Types::Address
|
@@ -9,7 +9,7 @@ module Unit
|
|
9
9
|
attribute :accept_deposits, Types::Boolean
|
10
10
|
attribute :surcharge_free, Types::Boolean
|
11
11
|
|
12
|
-
include
|
12
|
+
include ResourceOperations::List
|
13
13
|
|
14
14
|
def self.list_by_coordinates(latitude:, longitude:, search_radius:)
|
15
15
|
list(
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Unit
|
2
|
-
class DepositAccount <
|
2
|
+
class DepositAccount < APIResource
|
3
3
|
path '/accounts'
|
4
4
|
|
5
5
|
attribute :deposit_product, Types::String # The name of the deposit product
|
@@ -20,9 +20,9 @@ module Unit
|
|
20
20
|
|
21
21
|
belongs_to :customer, class_name: 'Unit::IndividualCustomer'
|
22
22
|
|
23
|
-
include
|
24
|
-
include
|
25
|
-
include
|
26
|
-
include
|
23
|
+
include ResourceOperations::List
|
24
|
+
include ResourceOperations::Create
|
25
|
+
include ResourceOperations::Save
|
26
|
+
include ResourceOperations::Find
|
27
27
|
end
|
28
28
|
end
|
@@ -1,33 +1,33 @@
|
|
1
1
|
module Unit
|
2
|
-
|
3
|
-
|
2
|
+
class IndividualApplication < APIResource
|
3
|
+
path '/applications'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
5
|
+
attribute :ssn, Types::String # SSN (or ITIN) of the individual (numbers only). Either an SSN or a passport number is required.
|
6
|
+
attribute :passport, Types::String # Passport number of the individual. Either an SSN or a passport number is required.
|
7
|
+
attribute :nationality, Types::String # Required on if a passport is used as the main ID. Two letters representing the individual nationality. (e.g. "US").
|
8
|
+
attribute :full_name, Types::FullName # Full name of the individual.
|
9
|
+
attribute :date_of_birth, Types::Date # RFC3339 Date only (e.g. "2001-08-15").
|
10
|
+
attribute :address, Types::Address # Address of the individual.
|
11
|
+
attribute :phone, Types::Phone # Phone number of the individual.
|
12
|
+
attribute :email, Types::String # Email address of the individual.
|
13
|
+
attribute :ip, Types::String # Optional. IP address of the end-customer creating the application. Both IPv4 and IPv6 formats are supported. Highly recommended as a fraud prevention measure, if the information is available when submitting the application.
|
14
|
+
attribute :sole_proprietorship, Types::Boolean # Optional. Default: false. Indicates whether the individual is a sole proprietor.
|
15
|
+
attribute :ein, Types::String # Optional. If the individual is a sole proprietor who has an Employer Identification Number, specify it here. Not all sole proprietors have an EIN, so this attribute is optional, even when soleProprietorship is set to true.
|
16
|
+
attribute :dba, Types::String # Optional. If the individual is a sole proprietor who is doing business under a different name, specify it here. This attribute is optional, even when soleProprietorship is set to true.
|
17
|
+
attribute :tags, Types::Hash # Optional. Tags that will be copied to the customer that this application creates
|
18
|
+
attribute :idempotency_key, Types::String # Optional
|
19
|
+
attribute :device_fingerprints, Types::Array # array of Device Fingerprint Optional. A list of device fingerprints for fraud and risk prevention
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
attribute :created_at, Types::DateTime, readonly: true
|
22
|
+
attribute :status, Types::String, readonly: true
|
23
|
+
attribute :message, Types::String, readonly: true
|
24
|
+
attribute :evaluation_id, Types::String, readonly: true
|
25
|
+
attribute :authorized_users, Types::Array, readonly: true
|
26
26
|
|
27
|
-
|
27
|
+
belongs_to :customer, class_name: 'Unit::IndividualCustomer'
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
include ResourceOperations::Find
|
30
|
+
include ResourceOperations::List
|
31
|
+
include ResourceOperations::Create
|
32
|
+
end
|
33
33
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Unit
|
2
|
-
class IndividualCustomer <
|
2
|
+
class IndividualCustomer < APIResource
|
3
3
|
path '/customers'
|
4
4
|
|
5
5
|
attribute :ssn, Types::String # SSN (or ITIN) of the individual (numbers only). Either an SSN or a passport number is required.
|
@@ -20,9 +20,9 @@ module Unit
|
|
20
20
|
|
21
21
|
belongs_to :application, class_name: 'Unit::IndividualApplication'
|
22
22
|
|
23
|
-
include
|
24
|
-
include
|
25
|
-
include
|
26
|
-
include
|
23
|
+
include ResourceOperations::List
|
24
|
+
include ResourceOperations::Create
|
25
|
+
include ResourceOperations::Save
|
26
|
+
include ResourceOperations::Find
|
27
27
|
end
|
28
28
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Unit
|
2
|
-
class IndividualDebitCard <
|
2
|
+
class IndividualDebitCard < APIResource
|
3
3
|
path '/cards'
|
4
4
|
|
5
5
|
attribute :shipping_address, Types::Address # Optional. Address to ship the card to. If not specified, the individual address is used.
|
@@ -17,9 +17,9 @@ module Unit
|
|
17
17
|
belongs_to :customer, class_name: 'Unit::IndividualCustomer'
|
18
18
|
belongs_to :account, class_name: 'Unit::DepositAccount'
|
19
19
|
|
20
|
-
include
|
21
|
-
include
|
22
|
-
include
|
23
|
-
include
|
20
|
+
include ResourceOperations::List
|
21
|
+
include ResourceOperations::Create
|
22
|
+
include ResourceOperations::Save
|
23
|
+
include ResourceOperations::Find
|
24
24
|
end
|
25
25
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Unit
|
2
|
-
class Institution <
|
2
|
+
class Institution < APIResource
|
3
3
|
attribute :routing_number, Types::String # Routing number of the institution. Valid 9-digit ABA routing transit number.
|
4
4
|
attribute :name, Types::String # Name of the institution.
|
5
5
|
attribute :address, Types::String # Optional. Address of the institution.
|
@@ -8,7 +8,7 @@ module Unit
|
|
8
8
|
|
9
9
|
path '/institutions'
|
10
10
|
|
11
|
-
include
|
11
|
+
include ResourceOperations::Find
|
12
12
|
|
13
13
|
def self.find_by(routing_number:)
|
14
14
|
find(routing_number)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Unit
|
2
|
+
class Transaction < APIResource
|
3
|
+
path '/transactions'
|
4
|
+
|
5
|
+
attribute :direction, Types::String
|
6
|
+
attribute :amount, Types::Integer
|
7
|
+
attribute :balance, Types::Integer
|
8
|
+
attribute :summary, Types::String
|
9
|
+
attribute :created_at, Types::DateTime, readonly: true
|
10
|
+
|
11
|
+
include ResourceOperations::List
|
12
|
+
end
|
13
|
+
end
|
data/lib/unit-ruby/types/date.rb
CHANGED
@@ -1,179 +1,180 @@
|
|
1
1
|
module Unit
|
2
|
-
|
3
|
-
|
4
|
-
attr_accessor :id, :type
|
2
|
+
class APIResource
|
3
|
+
attr_accessor :id, :type, :raw_data
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def initialize(attributes = {})
|
6
|
+
clear_attributes!
|
7
|
+
mark_as_clean!
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
end
|
9
|
+
attributes.each do |key, value|
|
10
|
+
send("#{key}=", value)
|
13
11
|
end
|
12
|
+
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
# Creates a base http connection to the API
|
15
|
+
#
|
16
|
+
def self.connection
|
17
|
+
@connection ||= Connection.new
|
18
|
+
end
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
# Defines the schema for a resource's attributes
|
21
|
+
#
|
22
|
+
def self.schema
|
23
|
+
@schema ||= Schema.new
|
24
|
+
end
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
def schema
|
27
|
+
self.class.schema
|
28
|
+
end
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
30
|
+
# Declares a new attribute by name and adds it to the schema
|
31
|
+
#
|
32
|
+
# @param name [Symbol] the name of the attribute
|
33
|
+
# @param type [Class] the object type
|
34
|
+
# @param readonly [Boolean] excludes the attribute from the request when creating a resource
|
35
|
+
def self.attribute(name, type = nil, readonly: false)
|
36
|
+
schema.add(name, type, readonly: readonly)
|
38
37
|
|
39
|
-
|
38
|
+
attr_accessor name
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
define_method("#{name}=") do |value|
|
41
|
+
previous_value = send(name)
|
42
|
+
new_value = type.cast(value)
|
44
43
|
|
45
|
-
|
44
|
+
instance_variable_set("@#{name}", new_value)
|
46
45
|
|
47
|
-
|
48
|
-
|
49
|
-
end
|
46
|
+
mark_attribute_as_dirty(name) if new_value != previous_value
|
47
|
+
new_value
|
50
48
|
end
|
49
|
+
end
|
51
50
|
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
def relationships
|
52
|
+
@relationships ||= {}
|
53
|
+
end
|
55
54
|
|
56
|
-
|
55
|
+
attr_writer :relationships
|
57
56
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
57
|
+
# Sets the base path for this resource
|
58
|
+
#
|
59
|
+
# Usage:
|
60
|
+
# class Customer < Unit::Resource
|
61
|
+
# path '/customers'
|
62
|
+
# end
|
63
|
+
def self.path(route = nil)
|
64
|
+
return @path if route.nil?
|
66
65
|
|
67
|
-
|
68
|
-
|
66
|
+
@path = route
|
67
|
+
end
|
69
68
|
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
def self.resource_path(id)
|
70
|
+
"#{path}/#{id}"
|
71
|
+
end
|
73
72
|
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
def self.resources_path
|
74
|
+
path
|
75
|
+
end
|
77
76
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
77
|
+
# The JSON:API type for this resource
|
78
|
+
def resource_type
|
79
|
+
self.class.name.split('::').last.camelize(:lower)
|
80
|
+
end
|
82
81
|
|
83
|
-
|
84
|
-
|
85
|
-
|
82
|
+
def resource_path
|
83
|
+
"#{self.class.path}/#{id}"
|
84
|
+
end
|
86
85
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
86
|
+
# Creates an association to a related resource
|
87
|
+
# This will create a helper method to traverse into a resource's related resource(s)
|
88
|
+
def self.belongs_to(resource_name, class_name: nil)
|
89
|
+
class_name ||= resource_name.to_s.camelize
|
91
90
|
|
92
|
-
|
93
|
-
|
91
|
+
define_method(resource_name) do
|
92
|
+
relationship_id = relationships[resource_name][:data]&.fetch(:id)
|
94
93
|
|
95
|
-
|
94
|
+
return nil unless relationship_id
|
96
95
|
|
97
|
-
|
98
|
-
|
96
|
+
Kernel.const_get(class_name).find(relationship_id)
|
97
|
+
end
|
99
98
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end
|
99
|
+
define_method("#{resource_name}=") do |resource|
|
100
|
+
relationships[resource_name] = {
|
101
|
+
data: { type: resource_name, id: resource.id }
|
102
|
+
}
|
105
103
|
end
|
104
|
+
end
|
106
105
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
end
|
106
|
+
# Hyrdates an instance of the resource from data returned from the API
|
107
|
+
def self.build_resource_from_json_api(data_item)
|
108
|
+
new.tap do |resource|
|
109
|
+
resource.mark_as_clean!
|
110
|
+
resource.update_resource_from_json_api(data_item)
|
113
111
|
end
|
112
|
+
end
|
114
113
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
114
|
+
def update_resource_from_json_api(data)
|
115
|
+
self.id = data[:id]
|
116
|
+
self.type = data[:type]
|
117
|
+
self.raw_data = data
|
118
|
+
self.relationships = data[:relationships]
|
119
119
|
|
120
|
-
|
120
|
+
clear_attributes!
|
121
121
|
|
122
|
-
|
122
|
+
data[:attributes].each { |key, value| update_attribute(key, value) }
|
123
123
|
|
124
|
-
|
125
|
-
|
124
|
+
mark_as_clean!
|
125
|
+
end
|
126
126
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
end
|
127
|
+
# Represents this resource's attributes
|
128
|
+
#
|
129
|
+
# @return [Hash] Representation of this resource's attributes as a hash
|
130
|
+
def attributes
|
131
|
+
self.class.schema.attributes.each_with_object({}) do |schema_attribute, h|
|
132
|
+
h[schema_attribute.name] = send(schema_attribute.name)
|
134
133
|
end
|
134
|
+
end
|
135
135
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
136
|
+
# Represents this resource for serialization (create/update)
|
137
|
+
#
|
138
|
+
# @return [Hash] Representation of this object as JSONAPI object
|
139
|
+
def as_json_api
|
140
|
+
self.class.schema.attributes.each_with_object({}) do |schema_attribute, h|
|
141
|
+
next if schema_attribute.readonly
|
142
142
|
|
143
|
-
|
143
|
+
val = send(schema_attribute.name)
|
144
144
|
|
145
|
-
|
146
|
-
|
145
|
+
# serialize the value if it is a complex type
|
146
|
+
val = val.as_json_api if val.respond_to? :as_json_api
|
147
147
|
|
148
|
-
|
149
|
-
end
|
148
|
+
h[schema_attribute.name] = val
|
150
149
|
end
|
150
|
+
end
|
151
151
|
|
152
|
-
|
153
|
-
|
154
|
-
|
152
|
+
def dirty?
|
153
|
+
dirty_attributes.any?
|
154
|
+
end
|
155
155
|
|
156
|
-
|
157
|
-
|
158
|
-
|
156
|
+
def dirty_attributes
|
157
|
+
@dirty_attributes ||= []
|
158
|
+
end
|
159
159
|
|
160
|
-
|
161
|
-
|
162
|
-
|
160
|
+
def mark_attribute_as_dirty(name)
|
161
|
+
dirty_attributes << name
|
162
|
+
end
|
163
163
|
|
164
|
-
|
165
|
-
|
166
|
-
|
164
|
+
def mark_as_clean!
|
165
|
+
@dirty_attributes = []
|
166
|
+
end
|
167
167
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
end
|
168
|
+
def clear_attributes!
|
169
|
+
schema.attributes.each do |attribute|
|
170
|
+
update_attribute(attribute.name, nil)
|
172
171
|
end
|
172
|
+
end
|
173
173
|
|
174
|
-
|
175
|
-
|
176
|
-
|
174
|
+
def update_attribute(name, value)
|
175
|
+
return unless schema.contains? name
|
176
|
+
|
177
|
+
send("#{name}=", value)
|
177
178
|
end
|
178
179
|
end
|
179
180
|
end
|
@@ -1,72 +1,70 @@
|
|
1
1
|
module Unit
|
2
|
-
|
3
|
-
class
|
4
|
-
|
5
|
-
|
6
|
-
end
|
2
|
+
class Connection
|
3
|
+
class << self
|
4
|
+
attr_accessor :api_key, :base_url
|
5
|
+
end
|
7
6
|
|
8
|
-
|
7
|
+
attr_reader :connection
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
9
|
+
def initialize
|
10
|
+
@connection = Faraday.new(self.class.base_url) do |f|
|
11
|
+
f.headers['Authorization'] = "Bearer #{self.class.api_key}"
|
12
|
+
f.request :json # encode req bodies as JSON
|
13
|
+
f.request :retry # retry transient failures
|
14
|
+
f.response :follow_redirects # follow redirects
|
15
|
+
f.response :json # decode response bodies as JSON
|
18
16
|
end
|
17
|
+
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
# Executes a GET request to the API
|
20
|
+
#
|
21
|
+
# @return the resource (or array of resources) returned from the API
|
22
|
+
def get(path, params = nil)
|
23
|
+
response = connection.get(path, params)
|
25
24
|
|
26
|
-
|
25
|
+
handle_errors(response)
|
27
26
|
|
28
|
-
|
27
|
+
from_json_api(response.body)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Executes a POST request to the API
|
31
|
+
#
|
32
|
+
# @return [Unit::APIResource] a new instance of the resource
|
33
|
+
def post(path, data = nil)
|
34
|
+
response = connection.post do |req|
|
35
|
+
req.url path
|
36
|
+
req.headers['Content-Type'] = 'application/vnd.api+json'
|
37
|
+
req.body = data.deep_transform_keys! { |key| key.to_s.camelize(:lower) } if data
|
29
38
|
end
|
30
39
|
|
31
|
-
|
32
|
-
#
|
33
|
-
# @return [Unit::APIResource] a new instance of the resource
|
34
|
-
def post(path, data = nil)
|
35
|
-
response = connection.post do |req|
|
36
|
-
req.url path
|
37
|
-
req.headers['Content-Type'] = 'application/vnd.api+json'
|
38
|
-
req.body = data.deep_transform_keys! { |key| key.to_s.camelize(:lower) } if data
|
39
|
-
end
|
40
|
+
handle_errors(response)
|
40
41
|
|
41
|
-
|
42
|
+
from_json_api(response.body)
|
43
|
+
end
|
42
44
|
|
43
|
-
|
45
|
+
# Executes a PATCH request to the API
|
46
|
+
def patch(path, data = nil)
|
47
|
+
response = connection.patch do |req|
|
48
|
+
req.url path
|
49
|
+
req.headers['Content-Type'] = 'application/vnd.api+json'
|
50
|
+
req.body = data.deep_transform_keys! { |key| key.to_s.camelize(:lower) } if data
|
44
51
|
end
|
45
52
|
|
46
|
-
|
47
|
-
def patch(path, data = nil)
|
48
|
-
response = connection.patch do |req|
|
49
|
-
req.url path
|
50
|
-
req.headers['Content-Type'] = 'application/vnd.api+json'
|
51
|
-
req.body = data.deep_transform_keys! { |key| key.to_s.camelize(:lower) } if data
|
52
|
-
end
|
53
|
+
handle_errors(response)
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
from_json_api(response.body)
|
57
|
-
end
|
55
|
+
from_json_api(response.body)
|
56
|
+
end
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
58
|
+
def from_json_api(response_body)
|
59
|
+
response_body.deep_transform_keys do |key|
|
60
|
+
key.to_s.underscore.to_sym
|
61
|
+
end.fetch(:data)
|
62
|
+
end
|
64
63
|
|
65
|
-
|
66
|
-
|
64
|
+
def handle_errors(response)
|
65
|
+
return if response.success?
|
67
66
|
|
68
|
-
|
69
|
-
end
|
67
|
+
raise(Error, response.body)
|
70
68
|
end
|
71
69
|
end
|
72
70
|
end
|
data/lib/unit-ruby/util/error.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
module Unit
|
2
|
-
|
3
|
-
|
4
|
-
attr_accessor :title, :status, :details, :detail
|
2
|
+
class Error < StandardError
|
3
|
+
attr_accessor :title, :status, :details, :detail
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
def initialize(api_response)
|
6
|
+
error = api_response['errors'].first
|
7
|
+
@title = error['title']
|
8
|
+
@status = error['status']
|
9
|
+
@details = error['details'] || error['detail']
|
11
10
|
|
12
|
-
|
13
|
-
end
|
11
|
+
super(@details)
|
14
12
|
end
|
15
13
|
end
|
16
14
|
end
|
@@ -1,81 +1,79 @@
|
|
1
1
|
module Unit
|
2
|
-
module
|
3
|
-
module
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
end
|
2
|
+
module ResourceOperations
|
3
|
+
module Find
|
4
|
+
def self.included(klass)
|
5
|
+
klass.extend(ClassMethods)
|
6
|
+
end
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
module ClassMethods
|
9
|
+
def find(id)
|
10
|
+
located_resource = connection.get(resource_path(id))
|
12
11
|
|
13
|
-
|
14
|
-
end
|
12
|
+
build_resource_from_json_api(located_resource)
|
15
13
|
end
|
16
14
|
end
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
module Create
|
18
|
+
def self.included(klass)
|
19
|
+
klass.extend(ClassMethods)
|
20
|
+
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
module ClassMethods
|
23
|
+
def create(attributes)
|
24
|
+
resource = new(attributes)
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
26
|
+
data = {
|
27
|
+
type: resource.resource_type,
|
28
|
+
attributes: resource.as_json_api.slice(*resource.dirty_attributes)
|
29
|
+
}
|
30
|
+
unless resource.relationships.empty?
|
31
|
+
data[:relationships] =
|
32
|
+
resource.relationships
|
33
|
+
end
|
35
34
|
|
36
|
-
|
35
|
+
created_resource = connection.post(resources_path, { data: data })
|
37
36
|
|
38
|
-
|
39
|
-
end
|
37
|
+
build_resource_from_json_api(created_resource)
|
40
38
|
end
|
41
39
|
end
|
40
|
+
end
|
42
41
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
module List
|
43
|
+
def self.included(klass)
|
44
|
+
klass.extend(ClassMethods)
|
45
|
+
end
|
47
46
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
47
|
+
module ClassMethods
|
48
|
+
# List resources
|
49
|
+
#
|
50
|
+
# @param where [Hash] Optional. Filters to apply to the list.
|
51
|
+
# @param limit [Integer] Optional. Maximum number of resources that will be returned. Maximum is 1000 resources.
|
52
|
+
# @param offset [Integer] Optional. Number of resources to skip
|
53
|
+
# @param sort [String] Optional. sort: 'createdAt' for ascending order or sort: '-createdAt' (leading minus sign) for descending order
|
54
|
+
def list(where: {}, limit: 100, offset: 0, sort: nil)
|
55
|
+
params = { filter: where, page: { offset: offset, limit: limit },
|
56
|
+
sort: sort }.compact
|
57
|
+
resources = connection.get(resources_path, params)
|
59
58
|
|
60
|
-
|
61
|
-
end
|
59
|
+
resources.map { |resource| build_resource_from_json_api(resource) }
|
62
60
|
end
|
63
61
|
end
|
62
|
+
end
|
64
63
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
}
|
64
|
+
module Save
|
65
|
+
def save
|
66
|
+
updated_resource = self.class.connection.patch(
|
67
|
+
resource_path,
|
68
|
+
{
|
69
|
+
data: {
|
70
|
+
type: resource_type,
|
71
|
+
attributes: as_json_api.slice(*dirty_attributes)
|
74
72
|
}
|
75
|
-
|
73
|
+
}
|
74
|
+
)
|
76
75
|
|
77
|
-
|
78
|
-
end
|
76
|
+
update_resource_from_json_api(updated_resource)
|
79
77
|
end
|
80
78
|
end
|
81
79
|
end
|
@@ -1,16 +1,18 @@
|
|
1
1
|
module Unit
|
2
|
-
|
3
|
-
|
4
|
-
Attribute = Struct.new(:name, :type, :readonly)
|
2
|
+
class Schema
|
3
|
+
Attribute = Struct.new(:name, :type, :readonly)
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def initialize
|
6
|
+
@attributes = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def contains?(name)
|
10
|
+
attributes.map(&:name).include? name
|
11
|
+
end
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
attr_reader :attributes
|
13
|
+
def add(name, type, readonly: false)
|
14
|
+
@attributes << Attribute.new(name, type, readonly)
|
14
15
|
end
|
16
|
+
attr_reader :attributes
|
15
17
|
end
|
16
18
|
end
|
data/lib/unit-ruby/version.rb
CHANGED
data/lib/unit-ruby.rb
CHANGED
@@ -12,7 +12,6 @@ require 'unit-ruby/types/boolean'
|
|
12
12
|
require 'unit-ruby/types/coordinates'
|
13
13
|
require 'unit-ruby/types/date_time'
|
14
14
|
require 'unit-ruby/types/date'
|
15
|
-
require 'unit-ruby/types/decimal'
|
16
15
|
require 'unit-ruby/types/float'
|
17
16
|
require 'unit-ruby/types/full_name'
|
18
17
|
require 'unit-ruby/types/hash'
|
@@ -27,6 +26,7 @@ require 'unit-ruby/individual_application'
|
|
27
26
|
require 'unit-ruby/individual_customer'
|
28
27
|
require 'unit-ruby/individual_debit_card'
|
29
28
|
require 'unit-ruby/institution'
|
29
|
+
require 'unit-ruby/transaction'
|
30
30
|
require 'unit-ruby/version'
|
31
31
|
|
32
32
|
module Unit
|
@@ -36,6 +36,6 @@ module Unit
|
|
36
36
|
# config.base_url = 'https://api.s.unit.sh'
|
37
37
|
# end
|
38
38
|
def self.configure
|
39
|
-
yield(
|
39
|
+
yield(Connection)
|
40
40
|
end
|
41
41
|
end
|
data/unit-ruby.gemspec
CHANGED
@@ -5,8 +5,8 @@ require 'unit-ruby/version'
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'unit-ruby'
|
7
7
|
spec.version = Unit::VERSION
|
8
|
-
spec.authors = ['Chloe Isacke']
|
9
|
-
spec.email = ['chloe@retirable.com']
|
8
|
+
spec.authors = ['Chloe Isacke', 'Ian Yamey']
|
9
|
+
spec.email = ['chloe@retirable.com', 'ian@retirable.com']
|
10
10
|
|
11
11
|
spec.summary = 'A Ruby gem for communicating with the Unit API.'
|
12
12
|
spec.homepage = 'https://github.com/retirable/unit-ruby'
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unit-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chloe Isacke
|
8
|
+
- Ian Yamey
|
8
9
|
autorequire:
|
9
10
|
bindir: exe
|
10
11
|
cert_chain: []
|
11
|
-
date: 2022-
|
12
|
+
date: 2022-02-15 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: faraday
|
@@ -83,14 +84,17 @@ dependencies:
|
|
83
84
|
description:
|
84
85
|
email:
|
85
86
|
- chloe@retirable.com
|
87
|
+
- ian@retirable.com
|
86
88
|
executables: []
|
87
89
|
extensions: []
|
88
90
|
extra_rdoc_files: []
|
89
91
|
files:
|
92
|
+
- ".github/workflows/ruby.yml"
|
90
93
|
- ".gitignore"
|
91
94
|
- ".rspec"
|
92
95
|
- ".rubocop.yml"
|
93
96
|
- ".travis.yml"
|
97
|
+
- CHANGELOG.md
|
94
98
|
- CODE_OF_CONDUCT.md
|
95
99
|
- Gemfile
|
96
100
|
- Gemfile.lock
|
@@ -107,6 +111,7 @@ files:
|
|
107
111
|
- lib/unit-ruby/individual_customer.rb
|
108
112
|
- lib/unit-ruby/individual_debit_card.rb
|
109
113
|
- lib/unit-ruby/institution.rb
|
114
|
+
- lib/unit-ruby/transaction.rb
|
110
115
|
- lib/unit-ruby/types/address.rb
|
111
116
|
- lib/unit-ruby/types/application_form_prefill.rb
|
112
117
|
- lib/unit-ruby/types/application_form_settings_override.rb
|
@@ -115,7 +120,6 @@ files:
|
|
115
120
|
- lib/unit-ruby/types/coordinates.rb
|
116
121
|
- lib/unit-ruby/types/date.rb
|
117
122
|
- lib/unit-ruby/types/date_time.rb
|
118
|
-
- lib/unit-ruby/types/decimal.rb
|
119
123
|
- lib/unit-ruby/types/float.rb
|
120
124
|
- lib/unit-ruby/types/full_name.rb
|
121
125
|
- lib/unit-ruby/types/hash.rb
|