unit-ruby 0.1.0 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a3f2e3572e786099dd10fd18ff168fcd0a01818584e99aebe5a4e8f7999ba5f
4
- data.tar.gz: f121f0016bcba17e49250155b5f6f9fb396197e19f36e90cee35b8c527fc7439
3
+ metadata.gz: 28b28032ddbe1492ec95f1d4c5cea1564d846a3f93896c777e2c6440b185a55a
4
+ data.tar.gz: 5bb4f8338d3fdef99579a9b5f197b3516ac775e817163925167d05359f490f5b
5
5
  SHA512:
6
- metadata.gz: d87105ca7f84244f906a1c2d88f10fd93224e7f0e59a714eeadc24cee4f0c10070ec22974597ad689a948debf2860699e68c777a758baef2767a3e12ef7a6027
7
- data.tar.gz: 75cf35de299db78b476823befd47efaf5c442c48ef550f39593b91ef46e14b4bfe6288508333dbd7f65a20bb4ab207b1c048ca0ed2b835e3baa5011dcd08a92b
6
+ metadata.gz: 9b1cd24b58f9732e3f9ec0b9bc17f099d168dca9f05de60c8caa7082c387ef3d50a8363af85afe8cf0b39cfcd25af433058d2020eb38bcf586c21ea4bac23ef2
7
+ data.tar.gz: 13d02249eb4a6f90bf059861c2b3890d2b4b48294ce89557818633b148ea5da584a92cf6dffb5627400c063475d2877ea5e932ab2c78d03d92a70e95014249e4
@@ -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/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ Initial release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- unit-ruby (0.1.0)
4
+ unit-ruby (0.1.3)
5
5
  faraday (~> 1.8.0)
6
6
 
7
7
  GEM
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2022 Chloe Isacke
3
+ Copyright (c) 2022 Retirable Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'bundler/setup'
4
- require 'unit/ruby'
4
+ require 'unit-ruby'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -1,14 +1,18 @@
1
1
  module Unit
2
- class ApplicationForm < Util::APIResource
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
- include Util::ResourceOperations::Create
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 < Util::APIResource
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 Util::ResourceOperations::List
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 < Util::APIResource
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 Util::ResourceOperations::List
24
- include Util::ResourceOperations::Create
25
- include Util::ResourceOperations::Save
26
- include Util::ResourceOperations::Find
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
- class IndividualApplication < Util::APIResource
3
- path '/applications'
2
+ class IndividualApplication < APIResource
3
+ path '/applications'
4
4
 
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
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
- 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
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
- belongs_to :customer, class_name: 'Unit::IndividualCustomer'
27
+ belongs_to :customer, class_name: 'Unit::IndividualCustomer'
28
28
 
29
- include Util::ResourceOperations::Find
30
- include Util::ResourceOperations::List
31
- include Util::ResourceOperations::Create
32
- end
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 < Util::APIResource
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 Util::ResourceOperations::List
24
- include Util::ResourceOperations::Create
25
- include Util::ResourceOperations::Save
26
- include Util::ResourceOperations::Find
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 < Util::APIResource
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 Util::ResourceOperations::List
21
- include Util::ResourceOperations::Create
22
- include Util::ResourceOperations::Save
23
- include Util::ResourceOperations::Find
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 < Util::APIResource
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 Util::ResourceOperations::Find
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 PinStatus < APIResource
3
+ path '/cards'
4
+
5
+ attribute :status, Types::String
6
+
7
+ def self.resource_path(id)
8
+ "#{super(id)}/secure-data/pin/status"
9
+ end
10
+
11
+ include ResourceOperations::Find
12
+ end
13
+ end
@@ -0,0 +1,31 @@
1
+ module Unit
2
+ class Statement < APIResource
3
+ path '/statements'
4
+
5
+ attribute :period, Types::String
6
+
7
+ def self.pdf_for(statement_id:, customer_id:)
8
+ url = base_url(statement_id, :pdf, customer_id)
9
+ statement_connection(url).get.body
10
+ end
11
+
12
+ def self.html_for(statement_id:, customer_id:)
13
+ url = base_url(statement_id, :html, customer_id)
14
+ statement_connection(url).get.body
15
+ end
16
+
17
+ def self.base_url(statement_id, response_type, customer_id)
18
+ "#{Unit::Connection.base_url}statements/#{statement_id}/#{response_type}" \
19
+ "?filter[customerId]=#{customer_id}"
20
+ end
21
+
22
+ def self.statement_connection(url)
23
+ # Establishing a new connection to avoid having to alter the existing connection to support pdf / html responses
24
+ Faraday.new(url) do |f|
25
+ f.headers['Authorization'] = "Bearer #{Unit::Connection.api_key}"
26
+ end
27
+ end
28
+
29
+ include ResourceOperations::List
30
+ end
31
+ end
@@ -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
@@ -50,7 +50,7 @@ module Unit
50
50
  cardholder_terms_url: cardholder_terms_url,
51
51
  cash_advanced_terms_url: cash_advanced_terms_url,
52
52
  additional_disclosures: additional_disclosures
53
- }
53
+ }.compact
54
54
  end
55
55
  end
56
56
  end
@@ -1,3 +1,5 @@
1
+ require 'date'
2
+
1
3
  module Unit
2
4
  module Types
3
5
  class Date
@@ -4,7 +4,7 @@ module Unit
4
4
  def self.cast(value)
5
5
  return nil if value.nil?
6
6
 
7
- ::Date.parse(value).iso8601
7
+ ::DateTime.parse(value).iso8601
8
8
  end
9
9
  end
10
10
  end
@@ -1,179 +1,176 @@
1
1
  module Unit
2
- module Util
3
- class APIResource
4
- attr_accessor :id, :type
2
+ class APIResource
3
+ attr_accessor :id, :type, :raw_data
5
4
 
6
- def initialize(attributes = {})
7
- clear_attributes!
8
- mark_as_clean!
5
+ def initialize(attributes = {})
6
+ clear_attributes!
7
+ mark_as_clean!
9
8
 
10
- attributes.each do |key, value|
11
- send("#{key}=", value)
12
- end
13
- end
14
-
15
- # Creates a base http connection to the API
16
- #
17
- def self.connection
18
- @connection ||= Connection.new
9
+ attributes.each do |key, value|
10
+ send("#{key}=", value)
19
11
  end
12
+ end
20
13
 
21
- # Defines the schema for a resource's attributes
22
- #
23
- def self.schema
24
- @schema ||= Util::Schema.new
25
- end
14
+ # Creates a base http connection to the API
15
+ #
16
+ def self.connection
17
+ @connection ||= Connection.new
18
+ end
26
19
 
27
- def schema
28
- self.class.schema
29
- end
20
+ # Defines the schema for a resource's attributes
21
+ #
22
+ def self.schema
23
+ @schema ||= Schema.new
24
+ end
30
25
 
31
- # Declares a new attribute by name and adds it to the schema
32
- #
33
- # @param name [Symbol] the name of the attribute
34
- # @param type [Class] the object type
35
- # @param readonly [Boolean] excludes the attribute from the request when creating a resource
36
- def self.attribute(name, type = nil, readonly: false)
37
- schema.add(name, type, readonly: readonly)
26
+ def schema
27
+ self.class.schema
28
+ end
38
29
 
39
- attr_accessor name
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)
40
37
 
41
- define_method("#{name}=") do |value|
42
- previous_value = send(name)
43
- new_value = type.cast(value)
38
+ attr_accessor name
44
39
 
45
- instance_variable_set("@#{name}", new_value)
40
+ define_method("#{name}=") do |value|
41
+ previous_value = send(name)
42
+ new_value = type.cast(value)
46
43
 
47
- mark_attribute_as_dirty(name) if new_value != previous_value
48
- new_value
49
- end
50
- end
44
+ instance_variable_set("@#{name}", new_value)
51
45
 
52
- def relationships
53
- @relationships ||= {}
46
+ mark_attribute_as_dirty(name) if new_value != previous_value
47
+ new_value
54
48
  end
49
+ end
55
50
 
56
- attr_writer :relationships
51
+ def relationships
52
+ @relationships ||= {}
53
+ end
57
54
 
58
- # Sets the base path for this resource
59
- #
60
- # Usage:
61
- # class Customer < Unit::Resource
62
- # path '/customers'
63
- # end
64
- def self.path(route = nil)
65
- return @path if route.nil?
55
+ attr_writer :relationships
66
56
 
67
- @path = route
68
- end
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?
69
65
 
70
- def self.resource_path(id)
71
- "#{path}/#{id}"
72
- end
66
+ @path = route
67
+ end
73
68
 
74
- def self.resources_path
75
- path
76
- end
69
+ def self.resource_path(id)
70
+ "#{path}/#{id}"
71
+ end
77
72
 
78
- # The JSON:API type for this resource
79
- def resource_type
80
- self.class.name.split('::').last.camelize(:lower)
81
- end
73
+ def self.resources_path
74
+ path
75
+ end
82
76
 
83
- def resource_path
84
- "#{self.class.path}/#{id}"
85
- end
77
+ # The JSON:API type for this resource
78
+ def resource_type
79
+ self.class.name.split('::').last.camelize(:lower)
80
+ end
86
81
 
87
- # Creates an association to a related resource
88
- # This will create a helper method to traverse into a resource's related resource(s)
89
- def self.belongs_to(resource_name, class_name: nil)
90
- class_name ||= resource_name.to_s.camelize
82
+ # Creates an association to a related resource
83
+ # This will create a helper method to traverse into a resource's related resource(s)
84
+ def self.belongs_to(resource_name, class_name: nil)
85
+ class_name ||= resource_name.to_s.camelize
91
86
 
92
- define_method(resource_name) do
93
- relationship_id = relationships[resource_name][:data]&.fetch(:id)
87
+ define_method(resource_name) do
88
+ relationship_id = relationships[resource_name][:data]&.fetch(:id)
94
89
 
95
- return nil unless relationship_id
90
+ return nil unless relationship_id
96
91
 
97
- Kernel.const_get(class_name).find(relationship_id)
98
- end
92
+ Kernel.const_get(class_name).find(relationship_id)
93
+ end
99
94
 
100
- define_method("#{resource_name}=") do |resource|
101
- relationships[resource_name] = {
102
- data: { type: resource_name, id: resource.id }
103
- }
104
- end
95
+ define_method("#{resource_name}=") do |resource|
96
+ relationships[resource_name] = {
97
+ data: { type: resource_name, id: resource.id }
98
+ }
105
99
  end
100
+ end
106
101
 
107
- # Hyrdates an instance of the resource from data returned from the API
108
- def self.build_resource_from_json_api(data_item)
109
- new.tap do |resource|
110
- resource.mark_as_clean!
111
- resource.update_resource_from_json_api(data_item)
112
- end
102
+ # Hyrdates an instance of the resource from data returned from the API
103
+ def self.build_resource_from_json_api(data_item)
104
+ new.tap do |resource|
105
+ resource.mark_as_clean!
106
+ resource.update_resource_from_json_api(data_item)
113
107
  end
108
+ end
114
109
 
115
- def update_resource_from_json_api(data)
116
- self.id = data[:id]
117
- self.type = data[:type]
118
- self.relationships = data[:relationships]
110
+ def update_resource_from_json_api(data)
111
+ self.id = data[:id]
112
+ self.type = data[:type]
113
+ self.raw_data = data
114
+ self.relationships = data[:relationships]
119
115
 
120
- clear_attributes!
116
+ clear_attributes!
121
117
 
122
- data[:attributes].each { |key, value| update_attribute(key, value) }
118
+ data[:attributes].each { |key, value| update_attribute(key, value) }
123
119
 
124
- mark_as_clean!
125
- end
120
+ mark_as_clean!
121
+ end
126
122
 
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)
133
- end
123
+ # Represents this resource's attributes
124
+ #
125
+ # @return [Hash] Representation of this resource's attributes as a hash
126
+ def attributes
127
+ self.class.schema.attributes.each_with_object({}) do |schema_attribute, h|
128
+ h[schema_attribute.name] = send(schema_attribute.name)
134
129
  end
130
+ end
135
131
 
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
132
+ # Represents this resource for serialization (create/update)
133
+ #
134
+ # @return [Hash] Representation of this object as JSONAPI object
135
+ def as_json_api
136
+ self.class.schema.attributes.each_with_object({}) do |schema_attribute, h|
137
+ next if schema_attribute.readonly
142
138
 
143
- val = send(schema_attribute.name)
139
+ val = send(schema_attribute.name)
144
140
 
145
- # serialize the value if it is a complex type
146
- val = val.as_json_api if val.respond_to? :as_json_api
141
+ # serialize the value if it is a complex type
142
+ val = val.as_json_api if val.respond_to? :as_json_api
147
143
 
148
- h[schema_attribute.name] = val
149
- end
144
+ h[schema_attribute.name] = val
150
145
  end
146
+ end
151
147
 
152
- def dirty?
153
- dirty_attributes.any?
154
- end
148
+ def dirty?
149
+ dirty_attributes.any?
150
+ end
155
151
 
156
- def dirty_attributes
157
- @dirty_attributes ||= []
158
- end
152
+ def dirty_attributes
153
+ @dirty_attributes ||= []
154
+ end
159
155
 
160
- def mark_attribute_as_dirty(name)
161
- dirty_attributes << name
162
- end
156
+ def mark_attribute_as_dirty(name)
157
+ dirty_attributes << name
158
+ end
163
159
 
164
- def mark_as_clean!
165
- @dirty_attributes = []
166
- end
160
+ def mark_as_clean!
161
+ @dirty_attributes = []
162
+ end
167
163
 
168
- def clear_attributes!
169
- self.class.schema.attributes.each do |attribute|
170
- update_attribute(attribute.name, nil)
171
- end
164
+ def clear_attributes!
165
+ schema.attributes.each do |attribute|
166
+ update_attribute(attribute.name, nil)
172
167
  end
168
+ end
173
169
 
174
- def update_attribute(name, value)
175
- send("#{name}=", value)
176
- end
170
+ def update_attribute(name, value)
171
+ return unless schema.contains? name
172
+
173
+ send("#{name}=", value)
177
174
  end
178
175
  end
179
176
  end
@@ -1,72 +1,70 @@
1
1
  module Unit
2
- module Util
3
- class Connection
4
- class << self
5
- attr_accessor :api_key, :base_url
6
- end
2
+ class Connection
3
+ class << self
4
+ attr_accessor :api_key, :base_url
5
+ end
7
6
 
8
- attr_reader :connection
7
+ attr_reader :connection
9
8
 
10
- def initialize
11
- @connection = Faraday.new(self.class.base_url) do |f|
12
- f.headers['Authorization'] = "Bearer #{self.class.api_key}"
13
- f.request :json # encode req bodies as JSON
14
- f.request :retry # retry transient failures
15
- f.response :follow_redirects # follow redirects
16
- f.response :json # decode response bodies as JSON
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
- # Executes a GET request to the API
21
- #
22
- # @return the resource (or array of resources) returned from the API
23
- def get(path, params = nil)
24
- response = connection.get(path, params)
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
- handle_errors(response)
25
+ handle_errors(response)
27
26
 
28
- from_json_api(response.body)
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
- # Executes a POST request to the API
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
- handle_errors(response)
42
+ from_json_api(response.body)
43
+ end
42
44
 
43
- from_json_api(response.body)
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
- # Executes a PATCH request to the API
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
- handle_errors(response)
55
-
56
- from_json_api(response.body)
57
- end
55
+ from_json_api(response.body)
56
+ end
58
57
 
59
- def from_json_api(response_body)
60
- response_body.deep_transform_keys do |key|
61
- key.to_s.underscore.to_sym
62
- end.fetch(:data)
63
- end
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
- def handle_errors(response)
66
- return if response.success?
64
+ def handle_errors(response)
65
+ return if response.success?
67
66
 
68
- raise(Error, response.body)
69
- end
67
+ raise(Error, response.body)
70
68
  end
71
69
  end
72
70
  end
@@ -1,16 +1,14 @@
1
1
  module Unit
2
- module Util
3
- class Error < StandardError
4
- attr_accessor :title, :status, :details, :detail
2
+ class Error < StandardError
3
+ attr_accessor :title, :status, :details, :detail
5
4
 
6
- def initialize(api_response)
7
- error = api_response['errors'].first
8
- @title = error['title']
9
- @status = error['status']
10
- @details = error['details'] || error['detail']
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
- super(@details)
13
- end
11
+ super(@details)
14
12
  end
15
13
  end
16
14
  end
@@ -1,81 +1,79 @@
1
1
  module Unit
2
- module Util
3
- module ResourceOperations
4
- module Find
5
- def self.included(klass)
6
- klass.extend(ClassMethods)
7
- end
2
+ module ResourceOperations
3
+ module Find
4
+ def self.included(klass)
5
+ klass.extend(ClassMethods)
6
+ end
8
7
 
9
- module ClassMethods
10
- def find(id)
11
- located_resource = connection.get(resource_path(id))
8
+ module ClassMethods
9
+ def find(id)
10
+ located_resource = connection.get(resource_path(id))
12
11
 
13
- build_resource_from_json_api(located_resource)
14
- end
12
+ build_resource_from_json_api(located_resource)
15
13
  end
16
14
  end
15
+ end
17
16
 
18
- module Create
19
- def self.included(klass)
20
- klass.extend(ClassMethods)
21
- end
17
+ module Create
18
+ def self.included(klass)
19
+ klass.extend(ClassMethods)
20
+ end
22
21
 
23
- module ClassMethods
24
- def create(attributes)
25
- resource = new(attributes)
22
+ module ClassMethods
23
+ def create(attributes)
24
+ resource = new(attributes)
26
25
 
27
- data = {
28
- type: resource.resource_type,
29
- attributes: resource.as_json_api.slice(*resource.dirty_attributes)
30
- }
31
- unless resource.relationships.empty?
32
- data[:relationships] =
33
- resource.relationships
34
- end
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
- created_resource = connection.post(resources_path, { data: data })
35
+ created_resource = connection.post(resources_path, { data: data })
37
36
 
38
- build_resource_from_json_api(created_resource)
39
- end
37
+ build_resource_from_json_api(created_resource)
40
38
  end
41
39
  end
40
+ end
42
41
 
43
- module List
44
- def self.included(klass)
45
- klass.extend(ClassMethods)
46
- end
42
+ module List
43
+ def self.included(klass)
44
+ klass.extend(ClassMethods)
45
+ end
47
46
 
48
- module ClassMethods
49
- # List resources
50
- #
51
- # @param where [Hash] Optional. Filters to apply to the list.
52
- # @param limit [Integer] Optional. Maximum number of resources that will be returned. Maximum is 1000 resources.
53
- # @param offset [Integer] Optional. Number of resources to skip
54
- # @param sort [String] Optional. sort: 'createdAt' for ascending order or sort: '-createdAt' (leading minus sign) for descending order
55
- def list(where: {}, limit: 100, offset: 0, sort: nil)
56
- params = { filter: where, page: { offset: offset, limit: limit },
57
- sort: sort }.compact
58
- resources = connection.get(resources_path, params)
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
- resources.map { |resource| build_resource_from_json_api(resource) }
61
- end
59
+ resources.map { |resource| build_resource_from_json_api(resource) }
62
60
  end
63
61
  end
62
+ end
64
63
 
65
- module Save
66
- def save
67
- updated_resource = self.class.connection.patch(
68
- resource_path,
69
- {
70
- data: {
71
- type: resource_type,
72
- attributes: as_json_api.slice(*dirty_attributes)
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
- update_resource_from_json_api(updated_resource)
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
- module Util
3
- class Schema
4
- Attribute = Struct.new(:name, :type, :readonly)
2
+ class Schema
3
+ Attribute = Struct.new(:name, :type, :readonly)
5
4
 
6
- def initialize
7
- @attributes = []
8
- end
5
+ def initialize
6
+ @attributes = []
7
+ end
8
+
9
+ def contains?(name)
10
+ attributes.map(&:name).include? name
11
+ end
9
12
 
10
- def add(name, type, readonly: false)
11
- @attributes << Attribute.new(name, type, readonly)
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
@@ -1,3 +1,3 @@
1
1
  module Unit
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.3'
3
3
  end
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,9 @@ 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/pin_status'
30
+ require 'unit-ruby/statement'
31
+ require 'unit-ruby/transaction'
30
32
  require 'unit-ruby/version'
31
33
 
32
34
  module Unit
@@ -36,6 +38,6 @@ module Unit
36
38
  # config.base_url = 'https://api.s.unit.sh'
37
39
  # end
38
40
  def self.configure
39
- yield(Util::Connection)
41
+ yield(Connection)
40
42
  end
41
43
  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.0
4
+ version: 0.1.3
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-01-24 00:00:00.000000000 Z
12
+ date: 2022-02-24 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,9 @@ 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/pin_status.rb
115
+ - lib/unit-ruby/statement.rb
116
+ - lib/unit-ruby/transaction.rb
110
117
  - lib/unit-ruby/types/address.rb
111
118
  - lib/unit-ruby/types/application_form_prefill.rb
112
119
  - lib/unit-ruby/types/application_form_settings_override.rb
@@ -115,7 +122,6 @@ files:
115
122
  - lib/unit-ruby/types/coordinates.rb
116
123
  - lib/unit-ruby/types/date.rb
117
124
  - lib/unit-ruby/types/date_time.rb
118
- - lib/unit-ruby/types/decimal.rb
119
125
  - lib/unit-ruby/types/float.rb
120
126
  - lib/unit-ruby/types/full_name.rb
121
127
  - lib/unit-ruby/types/hash.rb
@@ -1,9 +0,0 @@
1
- module Unit
2
- module Types
3
- class Decimal
4
- def self.cast(value)
5
- value&.to_d
6
- end
7
- end
8
- end
9
- end