vend 0.0.8 → 0.0.9
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/.rubocop.yml +57 -0
- data/README.rdoc +1 -1
- data/Rakefile +1 -1
- data/example.rb +3 -3
- data/lib/vend.rb +2 -1
- data/lib/vend/base.rb +12 -12
- data/lib/vend/base_factory.rb +2 -6
- data/lib/vend/client.rb +5 -5
- data/lib/vend/http_client.rb +30 -31
- data/lib/vend/null_logger.rb +9 -5
- data/lib/vend/oauth2/auth_code.rb +7 -10
- data/lib/vend/oauth2/client.rb +1 -5
- data/lib/vend/pagination_info.rb +2 -1
- data/lib/vend/resource/customer.rb +1 -3
- data/lib/vend/resource/outlet.rb +0 -2
- data/lib/vend/resource/payment_type.rb +0 -2
- data/lib/vend/resource/product.rb +0 -2
- data/lib/vend/resource/register.rb +0 -2
- data/lib/vend/resource/register_sale.rb +2 -5
- data/lib/vend/resource/register_sale_product.rb +1 -1
- data/lib/vend/resource/supplier.rb +23 -0
- data/lib/vend/resource/tax.rb +0 -2
- data/lib/vend/resource/user.rb +0 -2
- data/lib/vend/resource_collection.rb +11 -15
- data/lib/vend/scope.rb +1 -2
- data/lib/vend/version.rb +1 -1
- data/spec/integration/customer_spec.rb +12 -9
- data/spec/integration/outlet_spec.rb +2 -3
- data/spec/integration/payment_types_spec.rb +1 -2
- data/spec/integration/product_spec.rb +26 -29
- data/spec/integration/register_sale_spec.rb +9 -10
- data/spec/integration/register_spec.rb +1 -2
- data/spec/integration/supplier_spec.rb +14 -0
- data/spec/integration/tax_spec.rb +1 -2
- data/spec/integration/user_spec.rb +1 -2
- data/spec/mock_responses/suppliers.json +36 -0
- data/spec/spec_helper.rb +1 -2
- data/spec/support/matchers/have_attributes.rb +3 -3
- data/spec/support/shared_examples/integration.rb +7 -9
- data/spec/support/shared_examples/logger.rb +21 -10
- data/spec/vend/base_factory_spec.rb +11 -12
- data/spec/vend/base_spec.rb +22 -23
- data/spec/vend/client_spec.rb +40 -39
- data/spec/vend/http_client_spec.rb +70 -62
- data/spec/vend/null_logger_spec.rb +1 -1
- data/spec/vend/oauth2/auth_code_spec.rb +18 -17
- data/spec/vend/oauth2/client_spec.rb +21 -21
- data/spec/vend/pagination_info_spec.rb +40 -17
- data/spec/vend/resource/register_sale_product_spec.rb +8 -6
- data/spec/vend/resource/register_sale_spec.rb +7 -8
- data/spec/vend/resource_collection_spec.rb +108 -95
- data/spec/vend/scope_spec.rb +20 -12
- data/vend.gemspec +5 -6
- metadata +10 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64137299cf2287fec6feb5741e6f94d867ba0d43
|
4
|
+
data.tar.gz: 94ac4b34cb4b594b161bc19a8f7ad0733b25357e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22537fdc5eec7d1be785e5b4b3a4c4b9926df3b1da3509fa52f4c1f7af4171289ab42c2f65c8047d59e8ba9837675431ba4c2e70d672953720d8b1b3c5ccdcb2
|
7
|
+
data.tar.gz: 4b7ac00c0663fbd08df7b16308d49bd0394319f8c1bcb9598d6a6c14b36ec2028ffe497a2cef8603ca83b5cbde3e15063dc5eb19e6ecafdf88da1596ddf5a0f4
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# class Example
|
2
|
+
# ...
|
3
|
+
# private
|
4
|
+
# ...
|
5
|
+
# end
|
6
|
+
Style/AccessModifierIndentation:
|
7
|
+
EnforcedStyle: outdent
|
8
|
+
|
9
|
+
# Allows foo(bar: baz)
|
10
|
+
Style/BracesAroundHashParameters:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Style/DotPosition:
|
14
|
+
EnforcedStyle: leading
|
15
|
+
|
16
|
+
Style/IndentHash:
|
17
|
+
EnforcedStyle: consistent
|
18
|
+
|
19
|
+
Style/LineLength:
|
20
|
+
Max: 120
|
21
|
+
|
22
|
+
Style/RedundantSelf:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
# We like neatly-aligned code
|
26
|
+
Style/SingleSpaceBeforeFirstArg:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
Style/SpaceAroundEqualsInParameterDefault:
|
30
|
+
Enabled: false
|
31
|
+
|
32
|
+
Style/SpaceInsideHashLiteralBraces:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
# Allow single or double quotes
|
36
|
+
Style/StringLiterals:
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
# Disable this until we can work out how to allow aligning of assignments
|
40
|
+
# https://github.com/bbatsov/rubocop/blob/master/spec/rubocop/cop/style/extra_spacing_spec.rb#L23
|
41
|
+
Style/ExtraSpacing:
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
Style/WordArray:
|
45
|
+
Enabled: false
|
46
|
+
|
47
|
+
Style/NumericLiterals:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
Style/SignalException:
|
51
|
+
Enabled: false
|
52
|
+
|
53
|
+
Metrics/ClassLength:
|
54
|
+
Enabled: false
|
55
|
+
|
56
|
+
Style/MultilineOperationIndentation:
|
57
|
+
Enabled: false
|
data/README.rdoc
CHANGED
@@ -5,7 +5,7 @@ This gem provides access to Vend's REST API.
|
|
5
5
|
== Vend API Documentation
|
6
6
|
|
7
7
|
At the time of writing, this is located at
|
8
|
-
https://
|
8
|
+
https://developers.vendhq.com/documentation
|
9
9
|
|
10
10
|
== Using Vend API via Oauth 2.0
|
11
11
|
|
data/Rakefile
CHANGED
data/example.rb
CHANGED
@@ -5,7 +5,7 @@ STORE = ARGV[0]
|
|
5
5
|
USERNAME = ARGV[1]
|
6
6
|
PASSWORD = ARGV[2]
|
7
7
|
|
8
|
-
unless STORE
|
8
|
+
unless STORE && USERNAME && PASSWORD
|
9
9
|
$stderr.puts "Usage: example.rb store username password"
|
10
10
|
exit 1
|
11
11
|
end
|
@@ -16,7 +16,7 @@ logger = Log4r::Logger.new 'vend'
|
|
16
16
|
logger.outputters = Log4r::Outputter.stdout
|
17
17
|
client.http_client.logger = client.logger = logger
|
18
18
|
|
19
|
-
# puts client.request('products', :
|
19
|
+
# puts client.request('products', method: :put, body: '{"foo":"bar"}')
|
20
20
|
|
21
21
|
# puts "###### Products ######"
|
22
22
|
# client.Product.all.each do |product|
|
@@ -29,7 +29,7 @@ client.http_client.logger = client.logger = logger
|
|
29
29
|
# end
|
30
30
|
#
|
31
31
|
# puts "###### Creating a Customer ######"
|
32
|
-
# response = client.request('customers', :
|
32
|
+
# response = client.request('customers', method: :post, body: '{"customer_code":"foo"}')
|
33
33
|
# puts response
|
34
34
|
#
|
35
35
|
# puts "###### Finding a Customer by name ######"
|
data/lib/vend.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__))
|
2
2
|
require 'active_support/inflector'
|
3
3
|
|
4
4
|
require 'vend/exception'
|
@@ -19,6 +19,7 @@ require 'vend/resource/register_sale'
|
|
19
19
|
require 'vend/resource/register_sale_product'
|
20
20
|
require 'vend/resource/tax'
|
21
21
|
require 'vend/resource/user'
|
22
|
+
require 'vend/resource/supplier'
|
22
23
|
|
23
24
|
require 'vend/http_client'
|
24
25
|
require 'vend/client'
|
data/lib/vend/base.rb
CHANGED
@@ -5,7 +5,6 @@ module Vend
|
|
5
5
|
# Not all CRUD actions are available for every resource, and at current there
|
6
6
|
# is no PUT endpoint and hence no update action
|
7
7
|
class Base
|
8
|
-
|
9
8
|
# Reference to the Vend::Client client object providing the HTTP interface to the
|
10
9
|
# API
|
11
10
|
attr_reader :client
|
@@ -26,6 +25,7 @@ module Vend
|
|
26
25
|
def self.attribute_casts
|
27
26
|
@attribute_casts ||= {}
|
28
27
|
end
|
28
|
+
|
29
29
|
# Returns the endpoint name for the resource, used in API urls when making
|
30
30
|
# requests.
|
31
31
|
def self.endpoint_name
|
@@ -82,7 +82,7 @@ module Vend
|
|
82
82
|
#
|
83
83
|
# And return the corresponding collection of resources
|
84
84
|
def self.url_scope(method_name)
|
85
|
-
(class << self
|
85
|
+
(class << self; self; end).instance_eval do
|
86
86
|
define_method(method_name) do |client, arg|
|
87
87
|
initialize_collection(client, collection_name).scope(method_name, arg)
|
88
88
|
end
|
@@ -91,26 +91,26 @@ module Vend
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def self.findable_by(field, options = {})
|
94
|
-
|
95
|
-
(class << self ; self ; end).instance_eval do
|
94
|
+
(class << self; self; end).instance_eval do
|
96
95
|
define_method("find_by_#{field}") do |client, *args|
|
97
96
|
search(client, options[:as] || field, *args)
|
98
97
|
end
|
99
98
|
end
|
100
99
|
end
|
100
|
+
|
101
101
|
# Sends a search request to the API and initializes a collection of Resources
|
102
102
|
# from the response.
|
103
103
|
# This method is only used internally by find_by_field methods.
|
104
104
|
def self.search(client, field, query)
|
105
105
|
initialize_collection(
|
106
|
-
client, collection_name, :
|
106
|
+
client, collection_name, url_params: { field.to_sym => query }
|
107
107
|
)
|
108
108
|
end
|
109
109
|
|
110
110
|
# Builds a new instance of the described resource using the specified
|
111
111
|
# attributes.
|
112
112
|
def self.build(client, attrs)
|
113
|
-
self.new(client, :
|
113
|
+
self.new(client, attrs: attrs)
|
114
114
|
end
|
115
115
|
|
116
116
|
# Builds a collection of instances from a JSON response
|
@@ -131,7 +131,6 @@ module Vend
|
|
131
131
|
ResourceCollection.new(client, self, endpoint, args)
|
132
132
|
end
|
133
133
|
|
134
|
-
|
135
134
|
# Attempts to pull a singular object from Vend through the singular GET
|
136
135
|
# endpoint.
|
137
136
|
def self.find(client, id)
|
@@ -150,7 +149,7 @@ module Vend
|
|
150
149
|
# request. I.e, to default to 500 items per page:
|
151
150
|
#
|
152
151
|
# def default_collection_request_args
|
153
|
-
# super.merge(:
|
152
|
+
# super.merge(url_params: {page_size: 500})
|
154
153
|
# end
|
155
154
|
#
|
156
155
|
def self.default_collection_request_args
|
@@ -169,7 +168,7 @@ module Vend
|
|
169
168
|
|
170
169
|
# Overrides method_missing to query the attrs hash for the value stored
|
171
170
|
# at the specified key before proxying it to the object
|
172
|
-
def method_missing(method_name, *
|
171
|
+
def method_missing(method_name, *_args, &_block)
|
173
172
|
if attrs.keys.include? method_name.to_s
|
174
173
|
attribute_value_for(method_name)
|
175
174
|
else
|
@@ -191,13 +190,14 @@ module Vend
|
|
191
190
|
def delete!
|
192
191
|
raise(Vend::Resource::IllegalAction,
|
193
192
|
"#{self.class.name} has no unique ID") unless attrs['id']
|
194
|
-
client.request(singular_name, :
|
193
|
+
client.request(singular_name, method: :delete)
|
195
194
|
true
|
196
195
|
end
|
197
196
|
|
198
|
-
|
197
|
+
protected
|
198
|
+
|
199
199
|
def attribute_value_for(attribute_name)
|
200
|
-
if self.class.attribute_casts.
|
200
|
+
if self.class.attribute_casts.key? attribute_name
|
201
201
|
case self.class.attribute_casts[attribute_name].to_s
|
202
202
|
when "Float"
|
203
203
|
return attrs[attribute_name.to_s].to_f
|
data/lib/vend/base_factory.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module Vend
|
2
|
-
|
3
2
|
class BaseFactory
|
4
|
-
|
5
3
|
attr_reader :client, :target_class
|
6
4
|
|
7
5
|
def initialize(client, target_class)
|
@@ -22,13 +20,11 @@ module Vend
|
|
22
20
|
end
|
23
21
|
|
24
22
|
## Generates find_by_field methods which call a search on the target class
|
25
|
-
#def self.findable_by(field, options = {})
|
23
|
+
# def self.findable_by(field, options = {})
|
26
24
|
# url_param = options[:as] || field
|
27
25
|
# define_method "find_by_#{field.to_s}" do |*args|
|
28
26
|
# target_class.send(:search, @client, url_param, *args)
|
29
27
|
# end
|
30
|
-
#end
|
31
|
-
|
28
|
+
# end
|
32
29
|
end
|
33
|
-
|
34
30
|
end
|
data/lib/vend/client.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
|
3
3
|
module Vend #:nodoc:
|
4
|
-
|
5
4
|
# Main access point which allows resources within the Vend gem to
|
6
5
|
# make HTTP requests to the Vend API.
|
7
6
|
#
|
@@ -10,7 +9,6 @@ module Vend #:nodoc:
|
|
10
9
|
# * a valid username and password
|
11
10
|
#
|
12
11
|
class Client
|
13
|
-
|
14
12
|
DEFAULT_OPTIONS = {}
|
15
13
|
|
16
14
|
extend Forwardable
|
@@ -61,6 +59,10 @@ module Vend #:nodoc:
|
|
61
59
|
Vend::BaseFactory.new(self, Resource::User)
|
62
60
|
end
|
63
61
|
|
62
|
+
def Supplier #:nodoc:
|
63
|
+
Vend::BaseFactory.new(self, Resource::Supplier)
|
64
|
+
end
|
65
|
+
|
64
66
|
# Returns the base API url for the client.
|
65
67
|
# E.g. for the store 'foo', it returns https://foo.vendhq.com/api/
|
66
68
|
def base_url
|
@@ -73,10 +75,8 @@ module Vend #:nodoc:
|
|
73
75
|
|
74
76
|
def http_client_options
|
75
77
|
options.merge(
|
76
|
-
:
|
78
|
+
base_url: base_url, username: username, password: password
|
77
79
|
)
|
78
80
|
end
|
79
|
-
|
80
81
|
end
|
81
|
-
|
82
82
|
end
|
data/lib/vend/http_client.rb
CHANGED
@@ -3,7 +3,6 @@ require 'json'
|
|
3
3
|
require 'cgi'
|
4
4
|
module Vend
|
5
5
|
class HttpClient
|
6
|
-
|
7
6
|
UNAUTHORIZED_MESSAGE = "Client not authorized. Check your store credentials are correct and try again."
|
8
7
|
# Read timeout in seconds
|
9
8
|
READ_TIMEOUT = 240
|
@@ -11,14 +10,14 @@ module Vend
|
|
11
10
|
include Logable
|
12
11
|
|
13
12
|
attr_accessor :base_url, :verify_ssl, :username, :password, :auth_token
|
14
|
-
|
13
|
+
alias_method :verify_ssl?, :verify_ssl
|
15
14
|
|
16
15
|
def initialize(options = {})
|
17
16
|
@base_url = options[:base_url]
|
18
17
|
@username = options[:username]
|
19
18
|
@password = options[:password]
|
20
19
|
@auth_token = options[:auth_token]
|
21
|
-
@verify_ssl = if options.
|
20
|
+
@verify_ssl = if options.key?(:verify_ssl)
|
22
21
|
options[:verify_ssl]
|
23
22
|
else
|
24
23
|
true
|
@@ -44,27 +43,27 @@ module Vend
|
|
44
43
|
#
|
45
44
|
# An optional hash of arguments may be specified. Possible options include:
|
46
45
|
# :method - The HTTP method
|
47
|
-
# E.g. request('foo', :
|
46
|
+
# E.g. request('foo', method: :post) will perform a POST request for
|
48
47
|
# http://storeurl.vendhq.com/api/foo
|
49
48
|
#
|
50
49
|
# :url_params - The URL parameters for GET requests.
|
51
|
-
# E.g. request('foo', :
|
50
|
+
# E.g. request('foo', url_params: {bar: "baz"}) will request
|
52
51
|
# http://storeurl.vendhq.com/api/foo?bar=baz
|
53
52
|
#
|
54
53
|
# :id - The ID required for performing actions on specific resources
|
55
54
|
# (e.g. delete).
|
56
|
-
# E.g. request('foos', :
|
55
|
+
# E.g. request('foos', method: :delete, id: 1) will request
|
57
56
|
# DELETE http://storeurl.vendhq.com/api/foos/1
|
58
57
|
#
|
59
58
|
# :body - The request body
|
60
59
|
# E.g. For submitting a POST to http://storeurl.vendhq.com/api/foo
|
61
60
|
# with the JSON data {"baz":"baloo"} we would call
|
62
|
-
# request('foo', :
|
61
|
+
# request('foo', method: :post, body: '{\"baz\":\"baloo\"}'
|
63
62
|
#
|
64
63
|
def request(path, options = {})
|
65
|
-
options = {:
|
64
|
+
options = {method: :get, redirect_count: 0}.merge options
|
66
65
|
raise RedirectionLimitExceeded if options[:redirect_count] > 10
|
67
|
-
url = if path.
|
66
|
+
url = if path.is_a?(URI)
|
68
67
|
path
|
69
68
|
else
|
70
69
|
URI.parse(base_url + path)
|
@@ -72,7 +71,7 @@ module Vend
|
|
72
71
|
ssl = (url.scheme == 'https')
|
73
72
|
http = get_http_connection(url.host, url.port, ssl)
|
74
73
|
|
75
|
-
# FIXME extract method
|
74
|
+
# FIXME: extract method
|
76
75
|
method = ("Net::HTTP::" + options[:method].to_s.classify).constantize
|
77
76
|
request = method.new(url.path + url_params_for(options[:url_params]))
|
78
77
|
request.basic_auth username, password if username && password
|
@@ -81,16 +80,16 @@ module Vend
|
|
81
80
|
request.body = options[:body] if options[:body]
|
82
81
|
logger.debug url
|
83
82
|
response = http.request(request)
|
84
|
-
if response.
|
83
|
+
if response.is_a?(Net::HTTPRedirection)
|
85
84
|
location = URI.parse(response['location'])
|
86
85
|
logger.debug "Following redirect to %s" % [location]
|
87
86
|
options[:redirect_count] = options[:redirect_count] + 1
|
88
87
|
request(location, options)
|
89
88
|
else
|
90
|
-
raise Unauthorized.new(UNAUTHORIZED_MESSAGE) if response.
|
91
|
-
raise HTTPError.new(response) unless response.
|
89
|
+
raise Unauthorized.new(UNAUTHORIZED_MESSAGE) if response.is_a?(Net::HTTPUnauthorized)
|
90
|
+
raise HTTPError.new(response) unless response.is_a?(Net::HTTPSuccess)
|
92
91
|
logger.debug response
|
93
|
-
JSON.parse response.body unless response.body.nil?
|
92
|
+
JSON.parse response.body unless response.body.nil? || response.body.empty?
|
94
93
|
end
|
95
94
|
end
|
96
95
|
|
@@ -103,20 +102,22 @@ module Vend
|
|
103
102
|
end
|
104
103
|
end
|
105
104
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
105
|
+
# Internal method to parse URL parameters.
|
106
|
+
# Returns an empty string from a nil argument
|
107
|
+
#
|
108
|
+
# E.g. url_params_for({field: "value"}) will return ?field=value
|
109
|
+
# url_params_for({field: ["value1","value2"]}) will return ?field[]=value1&field[]=value2
|
110
|
+
|
111
|
+
protected
|
112
|
+
|
112
113
|
def url_params_for(options)
|
113
|
-
ary =
|
114
|
+
ary = []
|
114
115
|
if !options.nil?
|
115
|
-
options.each do |option,value|
|
116
|
+
options.each do |option, value|
|
116
117
|
if value.class == Array
|
117
|
-
ary << value.collect { |key| "#{option}%5B%5D=#{CGI
|
118
|
+
ary << value.collect { |key| "#{option}%5B%5D=#{CGI.escape(key.to_s)}" }.join('&')
|
118
119
|
else
|
119
|
-
ary << "#{option}=#{CGI
|
120
|
+
ary << "#{option}=#{CGI.escape(value.to_s)}"
|
120
121
|
end
|
121
122
|
end
|
122
123
|
'?'.concat(ary.join('&'))
|
@@ -125,15 +126,13 @@ module Vend
|
|
125
126
|
end
|
126
127
|
end
|
127
128
|
|
128
|
-
|
129
|
+
protected
|
130
|
+
|
129
131
|
# Modifies path with the provided options
|
130
132
|
def expand_path_with_options(path, options)
|
131
|
-
# FIXME - Remove from here
|
132
|
-
if options[:id]
|
133
|
-
|
134
|
-
end
|
135
|
-
return path
|
133
|
+
# FIXME: - Remove from here
|
134
|
+
path += "/#{options[:id]}" if options[:id]
|
135
|
+
path
|
136
136
|
end
|
137
|
-
|
138
137
|
end
|
139
138
|
end
|
data/lib/vend/null_logger.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
module Vend
|
2
2
|
class NullLogger
|
3
|
-
def debug(*
|
4
|
-
|
5
|
-
def
|
6
|
-
|
7
|
-
def
|
3
|
+
def debug(*_args); end
|
4
|
+
|
5
|
+
def info(*_args); end
|
6
|
+
|
7
|
+
def warn(*_args); end
|
8
|
+
|
9
|
+
def error(*_args); end
|
10
|
+
|
11
|
+
def fatal(*_args); end
|
8
12
|
end
|
9
13
|
end
|