ponto 1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 72c51c8d524e4611174a8e1cc4a4d477f824555a740b7deb230f46ebff7e15df
4
+ data.tar.gz: f8970d162c5ffd3679f3d1074df2fb05709024f5150b430715efd9cbb428e96b
5
+ SHA512:
6
+ metadata.gz: 353f69bdb7f9e9de81c91535b64887563388a3c85f95036d4d7a752ba190b41cc2d139b722320546c4ce98ccbbfe053c1a333469377418e3c6451486b80ffadb
7
+ data.tar.gz: 06ac1f093bcfcc6ae2e41a09f25e3996f52cdefe52193871687c2a07e7047e0c93d07f47fc48a0f3c1afb7481fde3b26587a0a6dd19c1ab2f2d84acf852ec849
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .DS_Store
16
+ .ruby*
17
+ *.gem
18
+ *.env
data/.gitkeep ADDED
File without changes
data/.travis.yml ADDED
@@ -0,0 +1,20 @@
1
+ language: ruby
2
+ script: bundle exec rspec
3
+ deploy:
4
+ provider: rubygems
5
+ on:
6
+ tags: true
7
+ gem: ponto
8
+ skip_cleanup: true
9
+ api_key:
10
+ secure: 17jdw6Oa2GbHKVLncFXo1eh/bFlJ3kdMOK2AWqPtlIDTpl/lWU8B5AfKysoOrDNWuiC/Qy7CeC0lhWbXAInbrh7A1QeNstWIZtccE3JA8YGV66JgnvOBhUG6NhdM9zu8/q6RyDiZ+oUnc6j4AlEu9zOFhd0sJMJRPQIOfwUyJgs2WTI1PZHT/iLuBU3twsL5JEWT8clCIlqxEQvjVp2GEAm8pDI5UO6bT0t2cQpBuTomGQfU02VwrWaDVa4IKTUclQFykgdHsU7sP6WE+mrep4wC4Nh32zuBFY6wy9e4VCmdoNuh+mGWB2hXT95Cf3N5JzEf2yRbXLL+VSdw90p/+u5uB6sofvO+Tg2Wy8ibukeuKug2ybd+V7JO1+DuZVuooq3i9diNAWIusYlScXe+0SiiWgBWewhjT6sJKsKlr6PgDceNuc7vrDkgvYGDn7YytnpA2yhOphOG9uqQtKBS5l4pDJSQ9gdnQ6s3GDY29+fcMta+z7sITDNN0kuSF6yzd/SLm6W6vy7oNjqDT+tHeDhXSA757xNGijT9DAAvtR1OQYNzW4EXgfkKJZGBMLA7jSPrLQp62klMKZAMgFlaCwPBzJahImJXdU1TW7RHGEKMGdklSuWyUo9XxBUxHFLTMlGCqqvXSpMi+cZvDs8zC3xSxXbBQd5ctyDGGVyiN4Y=
11
+ notifications:
12
+ email: false
13
+ slack:
14
+ - rooms:
15
+ - secure: Gnd8fTAuv30PF4GfUR9RVmEeJ9zyPJ+DS0LCuynDgnHZj8q3bV7TL7zGY39HNjn5C0GDhmVXy5ZbUj/VBo8wW69zrKTugqIzhu6FkVq7hOQIANkUWWqJ4bh13mX5LSS7F9klpBxMA9Q3dOPGSo1VTpJqGaCX1Jc0ffY4I2fK6IbdNAsoYV1/DQAjFAmzuqRYEmEfYO3brGvrhXHDtgfTVmNqRJIhYdstGmmIOhIC5zSgQrjXofxYtW+nZNifhW9KfknZJk2g2dwIZm271iJdx59JnDNB8nUGrPHBFMaux1Yc5TwQhamctYphNcnlBjztXvzIeOSmOZKekg0k06w1ySLYvJTkEpY+i2f7FU9VK2CTJR3SJwJN++iveQnispgEYUOxCdsXs7cGQPwsUymS7vw2h6qiHS1BFpyxpi1oP+g3ZagsA1CZOQcnagm0qyJ/A3twUGFG6p3PS9m3TrbIPN0aK0/t93jxKm8lbcC+OlpMJOMgMnajs86JU1s3I+8WDj3EKQzkg/zeZhzqyfW5BCvQxDgVLTca+WWNC+bLZLhDqvLrs23mNXFvKOKrt3j3hJjH0/JUxHImNMtInBCKxIpSOn8NiCUeiAl7O2vDRwqa0khbjc/nt0nJ6awf4ciqNMqCiUjX5NgLI4loTWU0V7mPANIa/eUCTTV5vmJHr3g=
16
+ if: "(tag =~ ^v) AND (branch = master)"
17
+ - rooms:
18
+ - secure: Gnd8fTAuv30PF4GfUR9RVmEeJ9zyPJ+DS0LCuynDgnHZj8q3bV7TL7zGY39HNjn5C0GDhmVXy5ZbUj/VBo8wW69zrKTugqIzhu6FkVq7hOQIANkUWWqJ4bh13mX5LSS7F9klpBxMA9Q3dOPGSo1VTpJqGaCX1Jc0ffY4I2fK6IbdNAsoYV1/DQAjFAmzuqRYEmEfYO3brGvrhXHDtgfTVmNqRJIhYdstGmmIOhIC5zSgQrjXofxYtW+nZNifhW9KfknZJk2g2dwIZm271iJdx59JnDNB8nUGrPHBFMaux1Yc5TwQhamctYphNcnlBjztXvzIeOSmOZKekg0k06w1ySLYvJTkEpY+i2f7FU9VK2CTJR3SJwJN++iveQnispgEYUOxCdsXs7cGQPwsUymS7vw2h6qiHS1BFpyxpi1oP+g3ZagsA1CZOQcnagm0qyJ/A3twUGFG6p3PS9m3TrbIPN0aK0/t93jxKm8lbcC+OlpMJOMgMnajs86JU1s3I+8WDj3EKQzkg/zeZhzqyfW5BCvQxDgVLTca+WWNC+bLZLhDqvLrs23mNXFvKOKrt3j3hJjH0/JUxHImNMtInBCKxIpSOn8NiCUeiAl7O2vDRwqa0khbjc/nt0nJ6awf4ciqNMqCiUjX5NgLI4loTWU0V7mPANIa/eUCTTV5vmJHr3g=
19
+ on_success: change
20
+ on_failure: always
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2018 Isabel NV
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # Ponto Ruby Library
2
+
3
+ The Ponto Ruby Library provides convenient wrappers around the Ponto API. The object attributes are dynamically defined based on the API response, supporting minor API changes seamlessly.
4
+
5
+ ## Documentation
6
+
7
+ Visit our [Ruby API docs](https://documentation.myponto.com/api/ruby).
8
+
9
+ ## Installation
10
+
11
+ ```
12
+ gem install "ponto"
13
+ ```
14
+
15
+ ### Requirements
16
+
17
+ * Ruby 2.0+.
18
+
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :console do
4
+ exec "irb -r Ponto -I ./lib"
5
+ end
data/lib/ponto.rb ADDED
@@ -0,0 +1,64 @@
1
+ require "ostruct"
2
+ require "openssl"
3
+ require "uri"
4
+ require "rest_client"
5
+ require "json"
6
+ require "securerandom"
7
+ require "base64"
8
+
9
+ require_relative "ponto/util"
10
+ require_relative "ponto/error"
11
+ require_relative "ponto/collection"
12
+ require_relative "ponto/client"
13
+ require_relative "ponto/api/base_resource"
14
+ require_relative "ponto/api/o_auth_resource"
15
+ require_relative "ponto/api/account"
16
+ require_relative "ponto/api/transaction"
17
+ require_relative "ponto/api/financial_institution"
18
+ require_relative "ponto/api/payment"
19
+ require_relative "ponto/api/synchronization"
20
+ require_relative "ponto/api/access_token"
21
+
22
+ module Ponto
23
+ class << self
24
+ def client
25
+ options = configuration.to_h.delete_if { |_, v| v.nil? }
26
+ @client ||= Ponto::Client.new(options)
27
+ end
28
+
29
+ def configure
30
+ @client = nil
31
+ @api_schema = nil
32
+ @configuration = nil
33
+ yield configuration
34
+ end
35
+
36
+ def configuration
37
+ @configuration ||= Struct.new(
38
+ :client_id,
39
+ :client_secret,
40
+ :token,
41
+ :api_scheme,
42
+ :api_host,
43
+ :api_port,
44
+ :ssl_ca_file
45
+ ).new
46
+ end
47
+
48
+ def api_schema
49
+ @api_schema ||= client.get(uri: client.base_uri)["links"]
50
+ end
51
+
52
+ def respond_to_missing?(method_name, include_private = false)
53
+ client.respond_to?(method_name, include_private)
54
+ end
55
+
56
+ def method_missing(method_name, *args, &block)
57
+ if client.respond_to?(method_name)
58
+ client.__send__(method_name, *args, &block)
59
+ else
60
+ super
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,13 @@
1
+ module Ponto
2
+ class AccessToken < Ponto::OAuthResource
3
+ def self.create
4
+ uri = Ponto.api_schema["oauth2"]["token"]
5
+ payload = URI.encode_www_form([["grant_type", "client_credentials"]])
6
+ headers = {
7
+ authorization: "Basic " + Base64.strict_encode64("#{Ponto.client.client_id}:#{Ponto.client.client_secret}"),
8
+ content_type: "application/x-www-form-urlencoded"
9
+ }
10
+ create_by_uri(uri: uri, payload: payload, headers: headers)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Ponto
2
+ class Account < Ponto::BaseResource
3
+ def self.list(headers: nil, access_token: nil, **query_params)
4
+ uri = Ponto.api_schema["accounts"].sub("{accountId}", "")
5
+ list_by_uri(uri: uri, query_params: query_params, headers: headers, access_token: access_token)
6
+ end
7
+
8
+ def self.find(id:, access_token: nil, headers: nil)
9
+ uri = Ponto.api_schema["accounts"].sub("{accountId}", id)
10
+ find_by_uri(uri: uri, headers: headers, access_token: access_token)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,105 @@
1
+ module Ponto
2
+ class BaseResource < OpenStruct
3
+ def self.create_by_uri(uri:, resource_type:, attributes:, access_token:, meta: nil)
4
+ payload = {
5
+ data: {
6
+ type: resource_type,
7
+ attributes: attributes
8
+ }
9
+ }
10
+ payload[:data][:meta] = meta if meta
11
+ raw_item = Ponto.client.post(uri: uri, payload: payload, access_token: access_token)
12
+ new(raw_item["data"])
13
+ end
14
+
15
+ def self.list_by_uri(uri:, access_token:, query_params: {}, headers: nil)
16
+ raw_response = Ponto.client.get(uri: uri, query_params: query_params, headers: headers, access_token: access_token)
17
+ items = raw_response["data"].map do |raw_item|
18
+ new(raw_item)
19
+ end
20
+ Ponto::Collection.new(
21
+ klass: self,
22
+ items: items,
23
+ links: raw_response["links"],
24
+ paging: raw_response.dig("meta", "paging"),
25
+ synchronized_at: raw_response.dig("meta", "synchronizedAt"),
26
+ latest_synchronization: raw_response.dig("meta", "latestSynchronization"),
27
+ )
28
+ end
29
+
30
+ def self.find_by_uri(uri:, access_token:, headers: nil)
31
+ new(find_raw_by_uri(uri: uri, headers: headers, access_token: access_token))
32
+ end
33
+
34
+ def self.find_raw_by_uri(uri:, access_token:, headers: nil)
35
+ raw_item = Ponto.client.get(uri: uri, headers: headers, access_token: access_token)
36
+ raw_item["data"]
37
+ end
38
+
39
+ def self.destroy_by_uri(uri:, access_token:, headers: nil)
40
+ raw_item = Ponto.client.delete(uri: uri, headers: headers, access_token: access_token)
41
+ new(raw_item["data"])
42
+ end
43
+
44
+ def initialize(raw)
45
+ attributes = prepare_attributes(raw)
46
+ super(attributes)
47
+
48
+ relationships = raw["relationships"] || {}
49
+ setup_relationships(relationships)
50
+
51
+ links = raw["links"] || {}
52
+ setup_links(links)
53
+
54
+ meta = raw["meta"] || {}
55
+ end
56
+
57
+ def reload!
58
+ reloaded = self.class.find_raw_by_uri(uri)
59
+ attributes = prepare_attributes(reloaded)
60
+ attributes.each do |key, value|
61
+ self[key] = value
62
+ end
63
+ self
64
+ end
65
+
66
+ private
67
+
68
+ def prepare_attributes(raw)
69
+ base = {
70
+ "id" => raw["id"],
71
+ }
72
+ attributes = raw["attributes"] || {}
73
+ meta = raw["meta"] || {}
74
+ params = base.merge(attributes).merge(meta)
75
+ Ponto::Util.underscorize_hash(params)
76
+ end
77
+
78
+ def setup_relationships(relationships)
79
+ relationships.each do |key, relationship|
80
+ if relationship["data"]
81
+ klass = Ponto.const_get(Ponto::Util.camelize(key))
82
+ method_name = Ponto::Util.underscore(key)
83
+ define_singleton_method(method_name) do |headers: nil|
84
+ klass.find_by_uri(uri: relationship["links"]["related"], headers: headers)
85
+ end
86
+ self[Ponto::Util.underscore("#{key}_id")] = relationship["data"]["id"]
87
+ else
88
+ singular_key = key[0..-2]
89
+ klass = Ponto.const_get(Ponto::Util.camelize(singular_key))
90
+ method_name = Ponto::Util.underscore(key)
91
+ define_singleton_method(method_name) do |headers: nil, **query_params|
92
+ uri = relationship["links"]["related"]
93
+ klass.list_by_uri(uri: uri, headers: headers, query_params: query_params)
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ def setup_links(links)
100
+ links.each do |key, link|
101
+ self[Ponto::Util.underscore("#{key}_link")] = link
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,13 @@
1
+ module Ponto
2
+ class FinancialInstitution < Ponto::BaseResource
3
+ def self.list(access_token: nil, **query_params)
4
+ uri = Ponto.api_schema["financialInstitutions"].sub("{financialInstitutionId}", "")
5
+ list_by_uri(uri: uri, query_params: query_params, access_token: access_token)
6
+ end
7
+
8
+ def self.find(id:, access_token: nil)
9
+ uri = Ponto.api_schema["financialInstitutions"].sub("{financialInstitutionId}", id)
10
+ find_by_uri(uri: uri, access_token: access_token)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Ponto
2
+ class OAuthResource < OpenStruct
3
+ def self.create_by_uri(uri:, payload:, headers: nil)
4
+ raw_item = Ponto.client.post(uri: uri, payload: payload, headers: headers)
5
+ raw_item = {} if raw_item == ""
6
+ new(raw_item)
7
+ end
8
+
9
+ def initialize(raw)
10
+ super(raw)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,30 @@
1
+ module Ponto
2
+ class Payment < Ponto::BaseResource
3
+ def self.create(account_id:, access_token: nil, **attributes)
4
+ path = Ponto.api_schema["account"]["payments"]
5
+ .gsub("{accountId}", account_id)
6
+ .gsub("{paymentId}", "")
7
+ uri = Ponto.client.build_uri(path)
8
+ create_by_uri(
9
+ uri: uri,
10
+ resource_type: "payment",
11
+ attributes: attributes,
12
+ access_token: access_token
13
+ )
14
+ end
15
+
16
+ def self.find(id:, account_id:, access_token:)
17
+ uri = Ponto.api_schema["account"]["payments"]
18
+ .gsub("{accountId}", account_id)
19
+ .sub("{paymentId}", id)
20
+ find_by_uri(uri: uri, access_token: access_token)
21
+ end
22
+
23
+ def self.delete(id:, account_id:, access_token:)
24
+ uri = Ponto.api_schema["account"]["payments"]
25
+ .gsub("{accountId}", account_id)
26
+ .sub("{paymentId}", id)
27
+ destroy_by_uri(uri: uri, access_token: access_token)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ module Ponto
2
+ class Synchronization < Ponto::BaseResource
3
+ def self.create(access_token: nil, **attributes)
4
+ uri = Ponto.api_schema["synchronizations"].sub("{synchronizationId}", "")
5
+ create_by_uri(uri: uri, resource_type: "synchronization", attributes: attributes, access_token: access_token)
6
+ end
7
+
8
+ def self.find(id:, access_token: nil)
9
+ uri = Ponto.api_schema["synchronizations"].sub("{synchronizationId}", id)
10
+ find_by_uri(uri: uri, access_token: access_token)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ module Ponto
2
+ class Transaction < Ponto::BaseResource
3
+ def self.list(account_id:, access_token: nil, headers: nil, **query_params)
4
+ uri = Ponto.api_schema["account"]["transactions"]
5
+ .sub("{accountId}", account_id)
6
+ .sub("{transactionId}", "")
7
+ list_by_uri(uri: uri, query_params: query_params, headers: headers, access_token: access_token)
8
+ end
9
+
10
+ def self.find(id:, access_token: nil, account_id:)
11
+ uri = Ponto.api_schema["account"]["transactions"]
12
+ .sub("{accountId}", account_id)
13
+ .sub("{transactionId}", id)
14
+ find_by_uri(uri: uri, access_token: access_token)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,68 @@
1
+ module Ponto
2
+ class Client
3
+
4
+ attr_reader :base_uri, :client_id, :client_secret
5
+
6
+ def initialize(token: nil, client_id: nil, client_secret: nil, api_scheme: "https", api_host: "api.myponto.com", api_port: "443", ssl_ca_file: nil)
7
+ @token = token
8
+ @client_id = client_id
9
+ @client_secret = client_secret
10
+ @base_uri = "#{api_scheme}://#{api_host}:#{api_port}"
11
+ @ssl_ca_file = ssl_ca_file
12
+ end
13
+
14
+ def get(uri:, query_params: {}, headers: nil, access_token: nil)
15
+ headers = build_headers(access_token: access_token, extra_headers: headers)
16
+ execute(method: :get, uri: uri, headers: headers, query_params: query_params)
17
+ end
18
+
19
+ def post(uri:, payload:, query_params: {}, headers: nil, access_token: nil)
20
+ headers = build_headers(access_token: access_token, extra_headers: headers)
21
+ execute(method: :post, uri: uri, headers: headers, query_params: query_params, payload: payload)
22
+ end
23
+
24
+ def patch(uri:, payload:, query_params: {}, access_token: nil)
25
+ headers = build_headers(access_token: access_token)
26
+ execute(method: :patch, uri: uri, headers: headers, query_params: query_params, payload: payload)
27
+ end
28
+
29
+ def delete(uri:, query_params: {}, access_token: nil, headers: nil)
30
+ headers = build_headers(access_token: access_token, extra_headers: headers)
31
+ execute(method: :delete, uri: uri, headers: headers, query_params: query_params)
32
+ end
33
+
34
+ def build_uri(path)
35
+ URI.join(@base_uri, path).to_s
36
+ end
37
+
38
+ private
39
+
40
+ def execute(method:, uri:, headers:, query_params: {}, payload: nil)
41
+ query = {
42
+ method: method,
43
+ url: uri,
44
+ headers: headers.merge(params: query_params),
45
+ payload: payload && headers[:content_type] == :json ? payload.to_json : payload,
46
+ ssl_ca_file: @ssl_ca_file
47
+ }
48
+ raw_response = RestClient::Request.execute(query) do |response, request, result, &block|
49
+ if response.code >= 400
50
+ body = JSON.parse(response.body)
51
+ raise Ponto::Error.new(body["errors"]), "Ponto request failed."
52
+ else
53
+ response.return!(&block)
54
+ end
55
+ end
56
+ JSON.parse(raw_response)
57
+ end
58
+
59
+ def build_headers(access_token: nil, extra_headers: nil)
60
+ headers = {
61
+ content_type: :json,
62
+ accept: :json,
63
+ }
64
+ headers[:authorization] = "Bearer #{access_token || @token}"
65
+ headers.merge(extra_headers || {})
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,43 @@
1
+ module Ponto
2
+ class Collection < DelegateClass(Array)
3
+ attr_accessor :page_limit,
4
+ :before_cursor,
5
+ :after_cursor,
6
+ :first_link,
7
+ :next_link,
8
+ :previous_link,
9
+ :latest_synchronization,
10
+ :synchronized_at
11
+
12
+ def initialize(
13
+ klass:,
14
+ items:,
15
+ paging:,
16
+ links:,
17
+ synchronized_at:,
18
+ latest_synchronization:
19
+ )
20
+ paging ||= {}
21
+ links ||= {}
22
+ @klass = klass
23
+ @page_limit = paging["limit"]
24
+ @before_cursor = paging["before"]
25
+ @after_cursor = paging["after"]
26
+ @first_link = links["first"]
27
+ @next_link = links["next"]
28
+ @previous_link = links["prev"]
29
+ @synchronized_at = synchronized_at
30
+ @latest_synchronization = latest_synchronization
31
+ super(items)
32
+ end
33
+
34
+ def inspect
35
+ result = "#<#{self.class.name}"
36
+ instance_variables.each do |instance_variable|
37
+ result +=" #{instance_variable}=#{instance_variable_get(instance_variable).inspect}"
38
+ end
39
+ result += ">"
40
+ result
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ module Ponto
2
+ class Error < StandardError
3
+ attr_reader :errors
4
+
5
+ def initialize(errors)
6
+ @errors = errors
7
+ end
8
+
9
+ def to_s
10
+ if @errors && @errors.size > 0
11
+ @errors.map do |error|
12
+ p error
13
+ if error["meta"] && error["meta"]["attribute"]
14
+ "* #{error["code"]}: '#{error["meta"]["attribute"]}' #{error["detail"]}"
15
+ elsif error["meta"] && error["meta"]["resource"]
16
+ "* #{error["code"]}: '#{error["meta"]["resource"]}' #{error["detail"]}"
17
+ else
18
+ "* #{error["code"]}: #{error["detail"]}"
19
+ end
20
+ end.join("\n")
21
+ else
22
+ super
23
+ end
24
+ end
25
+ end
26
+ end
data/lib/ponto/util.rb ADDED
@@ -0,0 +1,28 @@
1
+ module Ponto
2
+ module Util
3
+ def self.underscorize_hash(attributes)
4
+ attributes.keys.reduce({}) do |result, key|
5
+ result[underscore(key)] = attributes[key]
6
+ result
7
+ end
8
+ end
9
+
10
+ def self.underscore(camel_cased_word)
11
+ return camel_cased_word unless camel_cased_word =~ /[A-Z-]/
12
+ word = camel_cased_word.to_s.gsub(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
13
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
14
+ word.tr!("-", "_")
15
+ word.downcase!
16
+ word
17
+ end
18
+
19
+ def self.camelize(string, uppercase_first_letter = true)
20
+ string = if uppercase_first_letter
21
+ string.sub(/^[a-z\d]*/) { $&.capitalize }
22
+ else
23
+ string.sub(/^(?:(?=\b|[A-Z_])|\w)/) { $&.downcase }
24
+ end
25
+ string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{Regexp.last_match(1)}#{Regexp.last_match(2).capitalize}" }.gsub("/", "::")
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module Ponto
2
+ VERSION = "1.0"
3
+ end
data/ponto.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ponto/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ponto"
8
+ spec.version = Ponto::VERSION
9
+ spec.authors = ["Ponto"]
10
+ spec.email = ["info@ibanity.com"]
11
+ spec.summary = "Ponto Ruby Client"
12
+ spec.description = "A Ruby wrapper for the Ponto API."
13
+ spec.homepage = "https://documentation.myponto.com/api/ruby"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "rest-client", ">= 1.8.0"
22
+ spec.add_development_dependency "rspec", "3.4.0"
23
+ spec.add_development_dependency "webmock", "1.24.2"
24
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ponto
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Ponto
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.8.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.8.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 3.4.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 3.4.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: webmock
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.24.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.24.2
55
+ description: A Ruby wrapper for the Ponto API.
56
+ email:
57
+ - info@ibanity.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".gitkeep"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - lib/ponto.rb
70
+ - lib/ponto/api/access_token.rb
71
+ - lib/ponto/api/account.rb
72
+ - lib/ponto/api/base_resource.rb
73
+ - lib/ponto/api/financial_institution.rb
74
+ - lib/ponto/api/o_auth_resource.rb
75
+ - lib/ponto/api/payment.rb
76
+ - lib/ponto/api/synchronization.rb
77
+ - lib/ponto/api/transaction.rb
78
+ - lib/ponto/client.rb
79
+ - lib/ponto/collection.rb
80
+ - lib/ponto/error.rb
81
+ - lib/ponto/util.rb
82
+ - lib/ponto/version.rb
83
+ - ponto.gemspec
84
+ homepage: https://documentation.myponto.com/api/ruby
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubygems_version: 3.0.3
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Ponto Ruby Client
107
+ test_files: []