mondo 0.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 +7 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.travis.yml +15 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +13 -0
- data/Guardfile +6 -0
- data/LICENSE +22 -0
- data/README.md +85 -0
- data/Rakefile +82 -0
- data/lib/mondo/client.rb +157 -0
- data/lib/mondo/errors.rb +48 -0
- data/lib/mondo/resource.rb +29 -0
- data/lib/mondo/response.rb +29 -0
- data/lib/mondo/transaction.rb +40 -0
- data/lib/mondo/utils.rb +29 -0
- data/lib/mondo/version.rb +3 -0
- data/lib/mondo.rb +10 -0
- data/mondo.gemspec +23 -0
- data/spec/client_spec.rb +13 -0
- data/spec/spec_helper.rb +2 -0
- metadata +150 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f0ad81c1a965f26c73a422a50269614cfc126a41
|
4
|
+
data.tar.gz: 2f28b956a9746dac9c368ea4089e04816312ef64
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 672dbe7dae1285eab18e90d6bdef348ced0bc66abc09c43491fc0bfc0d88a5180f76ffc16ba5a727ec54450cbdd1ca5644431a8511ba69a0613376f469161a1c
|
7
|
+
data.tar.gz: 4ceba43608623a96f5b58e161014a7a7b4452c04731a5890d98ea78c3dabe11cff3c636bff91b94524760ea542fd73ce767d2f57bef5754befe695211673bf3e
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
gem "guard", "~> 0.8.8"
|
7
|
+
gem "rspec", "~> 3.1"
|
8
|
+
if RUBY_PLATFORM.downcase.include?("darwin")
|
9
|
+
gem "guard-rspec", "~> 0.5.4"
|
10
|
+
gem "rb-fsevent", "~> 0.9"
|
11
|
+
gem "growl", "~> 1.0.3"
|
12
|
+
end
|
13
|
+
end
|
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Mondo (Focus FS Ltd)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Mondo Ruby Client
|
2
|
+
|
3
|
+
The Mondo Ruby client provides a simple Ruby interface to the Mondo API.
|
4
|
+
|
5
|
+
API documentation, usage guides, and setup information can be found at [getmondo.co.uk/docs](https://getmondo.co.uk/docs/).
|
6
|
+
|
7
|
+
## Initialize your client
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
mondo = Mondo::Client.new(
|
11
|
+
token: YOUR_TOKEN,
|
12
|
+
account_id: YOUR_ACCOUNT_ID
|
13
|
+
)
|
14
|
+
```
|
15
|
+
|
16
|
+
## Configure a different API URL
|
17
|
+
```ruby
|
18
|
+
mondo.api_url = "https://otherurl.com"
|
19
|
+
```
|
20
|
+
|
21
|
+
## Ping
|
22
|
+
|
23
|
+
Check your client is configured correctly
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
mondo.ping
|
27
|
+
=> "pong"
|
28
|
+
```
|
29
|
+
|
30
|
+
## List Transactions
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
mondo.transactions
|
34
|
+
=> [
|
35
|
+
#<Mondo::Transaction -7GBP LOWER EAST SIDE DELI LONDON EC2A GBR tx_00008zphrT5MZQoOhLbTur>,
|
36
|
+
#<Mondo::Transaction -5GBP SACAT MARKS & SPENCER LONDON GBR tx_00008zqEXy8SiMLdEqVVmT>,
|
37
|
+
#<Mondo::Transaction -31GBP OZONE COFFEE ROASTERS UNITED KINGDO GBR tx_00008zrYsmW9IVgPz3bUiv>,
|
38
|
+
#<Mondo::Transaction -26GBP LAN TANA LONDON GBR tx_00008zru1CYoS6lW6nhpeD>,
|
39
|
+
#<Mondo::Transaction -5GBP PRET A MANGER LONDON GBR tx_00008zvemPnUEdNo8attNB>,
|
40
|
+
#<Mondo::Transaction -4GBP EXPRESS OFF LICENSE LONDON GBR tx_00008zxnkK6vh3rvN38W6z>,
|
41
|
+
#<Mondo::Transaction -13GBP LOWER EAST SIDE DELI LONDON EC2A GBR tx_00008zy3PP7LTxxiXVEXAn>,
|
42
|
+
#<Mondo::Transaction -6GBP OZONE COFFEE ROASTERS LONDON GBR tx_00008zy8VxynHJGWOqY3aD>,
|
43
|
+
#<Mondo::Transaction -28GBP FGW SELF SERVICE PADDINGTON GBR tx_00008zyGtoILjhPUwlZli5>,
|
44
|
+
#<Mondo::Transaction -6GBP EXPRESS OFF LICENSE LONDON GBR tx_00008zzwuRFvGsQCml15Kj>
|
45
|
+
]
|
46
|
+
|
47
|
+
mondo.transactions(expand: :merchant, limit: 3, since: "2015-08-10T23:00:00Z")
|
48
|
+
=> [
|
49
|
+
#<Mondo::Transaction -6GBP OZONE COFFEE ROASTERS LONDON GBR tx_00008zy8VxynHJGWOqY3aD>,
|
50
|
+
#<Mondo::Transaction -28GBP FGW SELF SERVICE PADDINGTON GBR tx_00008zyGtoILjhPUwlZli5>,
|
51
|
+
#<Mondo::Transaction -6GBP EXPRESS OFF LICENSE LONDON GBR tx_00008zzwuRFvGsQCml15Kj>
|
52
|
+
]
|
53
|
+
|
54
|
+
# TODO - make a Merchant object
|
55
|
+
mondo.transactions.last.merchant
|
56
|
+
=>
|
57
|
+
{
|
58
|
+
"id"=>"merch_00008z40hJLCkWMs15lQDx",
|
59
|
+
"group_id"=>"grp_00008yEdbBXWcsqVNdftbd",
|
60
|
+
"created"=>"2015-08-15T11:07:04Z",
|
61
|
+
"name"=>"East Midlands Trains",
|
62
|
+
"logo"=>"https://pbs.twimg.com/profile_images/532472643694235648/vxJSda4F_400x400.png",
|
63
|
+
"address"=>{
|
64
|
+
"address"=>"St Pancras Station",
|
65
|
+
"city"=>"London",
|
66
|
+
"region"=>"",
|
67
|
+
"country"=>"GBR",
|
68
|
+
"postcode"=>"NW1 2QP",
|
69
|
+
"latitude"=>51.531427,
|
70
|
+
"longitude"=>-0.126133
|
71
|
+
}
|
72
|
+
}
|
73
|
+
```
|
74
|
+
|
75
|
+
## Update Transaction Tags
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
tx = mondo.transactions.first
|
79
|
+
|
80
|
+
# You can store deeply-nested key-value data on metadata. All values are stored & returned as strings.
|
81
|
+
tx.metadata[:tags] += "#expenses" # tag this "expenses"
|
82
|
+
|
83
|
+
tx.save_metadata
|
84
|
+
=> true
|
85
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'yard'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
desc "Generate YARD documentation"
|
5
|
+
YARD::Rake::YardocTask.new do |t|
|
6
|
+
files = ['lib/**/*.rb', '-', 'CHANGELOG.md', 'LICENSE']
|
7
|
+
t.files = files.reject { |f| f =~ /seed|example/ }
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Run an IRB session with mondo pre-loaded"
|
11
|
+
task :console do
|
12
|
+
exec "irb -I lib -r mondo"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Run the specs"
|
16
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
17
|
+
t.rspec_opts = %w[--color]
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def generate_changelog(last_version, new_version)
|
22
|
+
commits = `git log v#{last_version}.. --oneline`.split("\n")
|
23
|
+
msgs = commits.map { |commit| commit.sub(/^[a-f0-9]+/, '-') }
|
24
|
+
date = Time.now.strftime("%B %d, %Y")
|
25
|
+
"## #{new_version} - #{date}\n\n#{msgs.join("\n")}\n\n\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def update_changelog(last_version, new_version)
|
29
|
+
contents = File.read('CHANGELOG.md')
|
30
|
+
if contents =~ /## #{new_version}/
|
31
|
+
puts "CHANGELOG already contains v#{new_version}, skipping"
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
changelog = generate_changelog(last_version, new_version)
|
35
|
+
File.open('CHANGELOG.md', 'w') { |f| f.write(changelog + contents) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def update_version_file(new_version)
|
39
|
+
path = "lib/#{Dir.glob('*.gemspec').first.split('.').first}/version.rb"
|
40
|
+
contents = File.read(path)
|
41
|
+
contents.sub!(/VERSION\s+=\s+["'][\d\.]+["']/, "VERSION = '#{new_version}'")
|
42
|
+
File.open(path, 'w') { |f| f.write(contents) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def bump_version(part)
|
46
|
+
last_version = `git tag -l --sort=v:refname | tail -1`.strip.sub(/^v/, '')
|
47
|
+
major, minor, patch = last_version.scan(/\d+/).map(&:to_i)
|
48
|
+
|
49
|
+
case part
|
50
|
+
when :major
|
51
|
+
major += 1
|
52
|
+
minor = patch = 0
|
53
|
+
when :minor
|
54
|
+
minor += 1
|
55
|
+
patch = 0
|
56
|
+
when :patch
|
57
|
+
patch += 1
|
58
|
+
end
|
59
|
+
new_version = "#{major}.#{minor}.#{patch}"
|
60
|
+
|
61
|
+
update_changelog(last_version, new_version)
|
62
|
+
puts "Updated CHANGELOG"
|
63
|
+
|
64
|
+
update_version_file(new_version)
|
65
|
+
puts "Updated version.rb"
|
66
|
+
end
|
67
|
+
|
68
|
+
desc "Update the version, auto-generating the changelog"
|
69
|
+
namespace :version do
|
70
|
+
namespace :bump do
|
71
|
+
task :major do
|
72
|
+
bump_version :major
|
73
|
+
end
|
74
|
+
task :minor do
|
75
|
+
bump_version :minor
|
76
|
+
end
|
77
|
+
task :patch do
|
78
|
+
bump_version :patch
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
data/lib/mondo/client.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
require 'oauth2'
|
3
|
+
require 'openssl'
|
4
|
+
require 'uri'
|
5
|
+
require 'cgi'
|
6
|
+
require 'time'
|
7
|
+
require 'base64'
|
8
|
+
|
9
|
+
module Mondo
|
10
|
+
class Client
|
11
|
+
DEFAULT_API_URL = 'https://api.getmondo.co.uk'
|
12
|
+
|
13
|
+
attr_accessor :access_token, :account_id, :api_url
|
14
|
+
|
15
|
+
def initialize(args = {})
|
16
|
+
Utils.symbolize_keys! args
|
17
|
+
self.access_token = args.fetch(:token)
|
18
|
+
self.account_id = args.fetch(:account_id, nil)
|
19
|
+
self.api_url = args.fetch(:api_url, DEFAULT_API_URL)
|
20
|
+
raise ClientError.new("You must provide a token") unless self.access_token
|
21
|
+
end
|
22
|
+
|
23
|
+
# Replies "pong"
|
24
|
+
def ping
|
25
|
+
api_request(:get, "/ping").parsed["ping"]
|
26
|
+
end
|
27
|
+
|
28
|
+
# Issue an GET request to the API server
|
29
|
+
#
|
30
|
+
# @note this method is for internal use
|
31
|
+
# @param [String] path the path that will be added to the API prefix
|
32
|
+
# @param [Hash] params query string parameters
|
33
|
+
# @return [Hash] hash the parsed response data
|
34
|
+
def api_get(path, params = {})
|
35
|
+
api_request(:get, path, :params => params)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Issue a POST request to the API server
|
39
|
+
#
|
40
|
+
# @note this method is for internal use
|
41
|
+
# @param [String] path the path that will be added to the API prefix
|
42
|
+
# @param [Hash] data a hash of data that will be sent as the request body
|
43
|
+
# @return [Hash] hash the parsed response data
|
44
|
+
def api_post(path, data = {})
|
45
|
+
api_request(:post, path, :data => data)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Issue a PUT request to the API server
|
49
|
+
#
|
50
|
+
# @note this method is for internal use
|
51
|
+
# @param [String] path the path that will be added to the API prefix
|
52
|
+
# @param [Hash] data a hash of data that will be sent as the request body
|
53
|
+
# @return [Hash] hash the parsed response data
|
54
|
+
def api_put(path, data = {})
|
55
|
+
api_request(:put, path, :data => data)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Issue a PATCH request to the API server
|
59
|
+
#
|
60
|
+
# @note this method is for internal use
|
61
|
+
# @param [String] path the path that will be added to the API prefix
|
62
|
+
# @param [Hash] data a hash of data that will be sent as the request body
|
63
|
+
# @return [Hash] hash the parsed response data
|
64
|
+
def api_patch(path, data = {})
|
65
|
+
api_request(:patch, path, :data => data)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Issue a DELETE request to the API server
|
69
|
+
#
|
70
|
+
# @note this method is for internal use
|
71
|
+
# @param [String] path the path that will be added to the API prefix
|
72
|
+
# @param [Hash] data a hash of data that will be sent as the request body
|
73
|
+
# @return [Hash] hash the parsed response data
|
74
|
+
def api_delete(path, data = {})
|
75
|
+
api_request(:delete, path, :data => data)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Issue a request to the API server, returning the full response
|
79
|
+
#
|
80
|
+
# @note this method is for internal use
|
81
|
+
# @param [Symbol] method the HTTP method to use (e.g. +:get+, +:post+)
|
82
|
+
# @param [String] path the path that will be added to the API prefix
|
83
|
+
# @option [Hash] opts additional request options (e.g. form data, params)
|
84
|
+
def api_request(method, path, opts = {})
|
85
|
+
request(method, path, opts)
|
86
|
+
end
|
87
|
+
|
88
|
+
# @method transaction
|
89
|
+
# @return [Transactions] all transactions for this user
|
90
|
+
def transactions(opts = {})
|
91
|
+
raise ClientError.new("You must provide an account id to query transactions") unless self.account_id
|
92
|
+
opts.merge!(account_id: self.account_id)
|
93
|
+
resp = api_get("/transactions", opts)
|
94
|
+
return resp unless resp.error.nil?
|
95
|
+
resp.parsed["transactions"].map { |tx| Transaction.new(tx, self) }
|
96
|
+
end
|
97
|
+
|
98
|
+
def user_agent
|
99
|
+
@user_agent ||=
|
100
|
+
begin
|
101
|
+
gem_info = "mondo-ruby/v#{Mondo::VERSION}"
|
102
|
+
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
|
103
|
+
ruby_version = RUBY_VERSION
|
104
|
+
ruby_version += " p#{RUBY_PATCHLEVEL}" if defined?(RUBY_PATCHLEVEL)
|
105
|
+
comment = ["#{ruby_engine} #{ruby_version}"]
|
106
|
+
comment << RUBY_PLATFORM if defined?(RUBY_PLATFORM)
|
107
|
+
"#{gem_info} (#{comment.join("; ")})"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
# Send a request to the Mondo API servers
|
114
|
+
#
|
115
|
+
# @param [Symbol] method the HTTP method to use (e.g. +:get+, +:post+)
|
116
|
+
# @param [String] path the path fragment of the URL
|
117
|
+
# @option [Hash] opts query string parameters, headers
|
118
|
+
def request(method, path, opts = {})
|
119
|
+
raise ClientError, 'Access token missing' unless @access_token
|
120
|
+
|
121
|
+
opts[:headers] = {} if opts[:headers].nil?
|
122
|
+
opts[:headers]['Accept'] = 'application/json'
|
123
|
+
opts[:headers]['Content-Type'] = 'application/json' unless method == :get
|
124
|
+
opts[:headers]['User-Agent'] = user_agent
|
125
|
+
opts[:headers]['Authorization'] = "Bearer #{@access_token}"
|
126
|
+
|
127
|
+
opts[:body] = MultiJson.encode(opts[:data]) if !opts[:data].nil?
|
128
|
+
path = URI.encode(path)
|
129
|
+
|
130
|
+
resp = connection.run_request(method, path, opts[:body], opts[:headers]) do |req|
|
131
|
+
req.params = opts[:params] if !opts[:params].nil?
|
132
|
+
end
|
133
|
+
|
134
|
+
response = Response.new(resp)
|
135
|
+
|
136
|
+
case response.status
|
137
|
+
when 301, 302, 303, 307
|
138
|
+
# TODO
|
139
|
+
when 200..299, 300..399
|
140
|
+
# on non-redirecting 3xx statuses, just return the response
|
141
|
+
response
|
142
|
+
when 400..599
|
143
|
+
error = ApiError.new(response)
|
144
|
+
raise(error, "Status code #{response.status}")
|
145
|
+
else
|
146
|
+
error = ApiError.new(response)
|
147
|
+
raise(error, "Unhandled status code value of #{response.status}")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# The Faraday connection object
|
152
|
+
def connection
|
153
|
+
@connection ||= Faraday.new(self.api_url, { ssl: { verify: false } })
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
data/lib/mondo/errors.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module Mondo
|
4
|
+
class Error < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
class ApiError < Error
|
8
|
+
attr_reader :response, :code, :description
|
9
|
+
|
10
|
+
def initialize(response)
|
11
|
+
@response = response
|
12
|
+
@code = response.status
|
13
|
+
|
14
|
+
begin
|
15
|
+
parsed_response = MultiJson.decode(response.body)
|
16
|
+
errors = parsed_response["error"] || parsed_response["errors"]
|
17
|
+
@description = stringify_errors(errors)
|
18
|
+
rescue MultiJson::ParseError
|
19
|
+
@description = response.body ? response.body.strip : "Unknown error"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
"#{super} [#{self.code}] #{self.description}"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def stringify_errors(errors)
|
30
|
+
case errors
|
31
|
+
when Array
|
32
|
+
errors.join(", ")
|
33
|
+
when Hash
|
34
|
+
errors.flat_map do |field, messages|
|
35
|
+
messages.map { |message| "#{field} #{message}" }
|
36
|
+
end.join(", ")
|
37
|
+
else
|
38
|
+
errors.to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class ClientError < Error
|
44
|
+
end
|
45
|
+
|
46
|
+
class SignatureError < Error
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Mondo
|
2
|
+
class Resource
|
3
|
+
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(hash={}, client)
|
7
|
+
self.raw_data = hash
|
8
|
+
self.client = client
|
9
|
+
hash.each { |key,val| send("#{key}=", val) if respond_to?("#{key}=") }
|
10
|
+
self.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def date_writer(*args)
|
15
|
+
args.each do |attr|
|
16
|
+
define_method("#{attr.to_s}=".to_sym) do |date|
|
17
|
+
date = date.is_a?(String) ? DateTime.parse(date) : date
|
18
|
+
instance_variable_set("@#{attr}", date)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def date_accessor(*args)
|
24
|
+
attr_reader *args
|
25
|
+
date_writer *args
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Mondo
|
2
|
+
class Response
|
3
|
+
attr_reader :response, :parsed
|
4
|
+
attr_accessor :error, :options
|
5
|
+
|
6
|
+
# Initializes a Response instance
|
7
|
+
#
|
8
|
+
# @param [Faraday::Response] response The Faraday response instance
|
9
|
+
def initialize(resp)
|
10
|
+
@response = resp
|
11
|
+
@parsed = -> { MultiJson.load(body) rescue body }.call
|
12
|
+
end
|
13
|
+
|
14
|
+
# The HTTP response headers
|
15
|
+
def headers
|
16
|
+
response.headers
|
17
|
+
end
|
18
|
+
|
19
|
+
# The HTTP response status code
|
20
|
+
def status
|
21
|
+
response.status
|
22
|
+
end
|
23
|
+
|
24
|
+
# The HTTP response body
|
25
|
+
def body
|
26
|
+
response.body || ''
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Mondo
|
2
|
+
class Transaction < Resource
|
3
|
+
|
4
|
+
attr_accessor :id,
|
5
|
+
:description,
|
6
|
+
:amount,
|
7
|
+
:currency,
|
8
|
+
:merchant,
|
9
|
+
:notes,
|
10
|
+
:metadata,
|
11
|
+
:raw_data
|
12
|
+
|
13
|
+
date_accessor :created
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#<#{self.class} #{self.amount_with_currency} #{self.description} #{id}>"
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
self.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
# TODO - proper currency library
|
24
|
+
def amount_with_currency
|
25
|
+
"#{amount/100}#{currency}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def save_metadata
|
29
|
+
self.client.api_patch("/transactions/#{self.id}", metadata: self.metadata)
|
30
|
+
end
|
31
|
+
|
32
|
+
def tags
|
33
|
+
metadata["tags"]
|
34
|
+
end
|
35
|
+
|
36
|
+
def tags=(t)
|
37
|
+
metadata["tags"] = t
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/mondo/utils.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Mondo
|
4
|
+
module Utils
|
5
|
+
extend self
|
6
|
+
|
7
|
+
# String Helpers
|
8
|
+
def camelize(str)
|
9
|
+
str.split('_').map(&:capitalize).join
|
10
|
+
end
|
11
|
+
|
12
|
+
def underscore(str)
|
13
|
+
str.gsub(/(.)([A-Z])/) { "#{$1}_#{$2.downcase}" }.downcase
|
14
|
+
end
|
15
|
+
|
16
|
+
# Hash Helpers
|
17
|
+
def symbolize_keys(hash)
|
18
|
+
symbolize_keys! hash.dup
|
19
|
+
end
|
20
|
+
|
21
|
+
def symbolize_keys!(hash)
|
22
|
+
hash.keys.each do |key|
|
23
|
+
sym_key = key.to_s.to_sym rescue key
|
24
|
+
hash[sym_key] = hash.delete(key) unless hash.key?(sym_key)
|
25
|
+
end
|
26
|
+
hash
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/mondo.rb
ADDED
data/mondo.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path('../lib/mondo/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.add_runtime_dependency 'oauth2', '~> 1.0'
|
5
|
+
gem.add_runtime_dependency 'multi_json', '~> 1.10'
|
6
|
+
|
7
|
+
gem.add_development_dependency 'rspec', '~> 2.13'
|
8
|
+
gem.add_development_dependency 'yard', '~> 0.8'
|
9
|
+
gem.add_development_dependency 'activesupport', '~> 3.2'
|
10
|
+
gem.add_development_dependency 'rake', '~> 10.3'
|
11
|
+
|
12
|
+
gem.authors = ['Tom Blomfield']
|
13
|
+
gem.description = %q{A Ruby wrapper for the Mondo API}
|
14
|
+
gem.email = ['engineering@getmondo.co.uk']
|
15
|
+
gem.files = `git ls-files`.split("\n")
|
16
|
+
gem.homepage = 'https://github.com/mondough/mondo-ruby'
|
17
|
+
gem.name = 'mondo'
|
18
|
+
gem.require_paths = ['lib']
|
19
|
+
gem.summary = %q{Ruby wrapper for the Mondo API}
|
20
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
gem.version = Mondo::VERSION.dup
|
22
|
+
gem.licenses = ['MIT']
|
23
|
+
end
|
data/spec/client_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mondo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tom Blomfield
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: oauth2
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.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.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: multi_json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.10'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.10'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.13'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.13'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.8'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.8'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activesupport
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.2'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.2'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.3'
|
97
|
+
description: A Ruby wrapper for the Mondo API
|
98
|
+
email:
|
99
|
+
- engineering@getmondo.co.uk
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".rspec"
|
106
|
+
- ".travis.yml"
|
107
|
+
- CHANGELOG.md
|
108
|
+
- Gemfile
|
109
|
+
- Guardfile
|
110
|
+
- LICENSE
|
111
|
+
- README.md
|
112
|
+
- Rakefile
|
113
|
+
- lib/mondo.rb
|
114
|
+
- lib/mondo/client.rb
|
115
|
+
- lib/mondo/errors.rb
|
116
|
+
- lib/mondo/resource.rb
|
117
|
+
- lib/mondo/response.rb
|
118
|
+
- lib/mondo/transaction.rb
|
119
|
+
- lib/mondo/utils.rb
|
120
|
+
- lib/mondo/version.rb
|
121
|
+
- mondo.gemspec
|
122
|
+
- spec/client_spec.rb
|
123
|
+
- spec/spec_helper.rb
|
124
|
+
homepage: https://github.com/mondough/mondo-ruby
|
125
|
+
licenses:
|
126
|
+
- MIT
|
127
|
+
metadata: {}
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
requirements: []
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 2.4.6
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: Ruby wrapper for the Mondo API
|
148
|
+
test_files:
|
149
|
+
- spec/client_spec.rb
|
150
|
+
- spec/spec_helper.rb
|