vending-machine 0.1.2 → 0.2.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8804a13fd883e7691d53c92783030068937095f5
4
+ data.tar.gz: 2bc3e2c3f83d0931b8c4b21a3cd6027f676afdb0
5
+ SHA512:
6
+ metadata.gz: 20adbb6dceb11c22a30fdcb12749b60f80e9da9aebd55a5a40eb9676cfe19985b75b364cedb7522afef6e1214d966b8172287e5cc456ae4b82bc54e8539f1175
7
+ data.tar.gz: 6539ab4faa6cce8598c6a5c10fb0256e6224df8ef102e695e74219c3e7db618099f8cd2913231e0b8e08877749e2987d5f2c5810447742d1290b77b07f9d2e83
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/README.md CHANGED
@@ -2,9 +2,12 @@
2
2
 
3
3
  Access your [Vend Store](http://vendhq.com) in Ruby! Vending Machine turns the [Vend API](http://docs.vendhq.com/) into Ruby objects, including type coercion and nested objects.
4
4
 
5
+
5
6
  ```ruby
6
- # Create an instance of your store
7
- store = Vend::Store.new('store_name', 'user_name', 'password')
7
+ # Create an instance of your store with Basic Auth
8
+ store = Vend::Store.new({:store_name => 'store_name', :username => 'user_name', :password => 'password'})
9
+ # Create an instance of your store with OAuth
10
+ store = Vend::Store.new({:store_name => 'store_name', :auth_token => 'auth_token'})
8
11
 
9
12
  # Get all your products
10
13
  store.products.order('name', 'ASC').map &:name
@@ -35,13 +38,27 @@ Or install it yourself as:
35
38
 
36
39
  ## Usage
37
40
 
41
+ ### Basic Auth and Oauth Support
42
+ Authentication defaults to Basic Auth. You can switch to Oauth by adding the following code to an initializer.
43
+
44
+ ```ruby
45
+ # config/vending_machine.rb
46
+ Vend.config do |config|
47
+ config.auth_method = :oauth # defaults to :basic_auth
48
+ end
49
+
50
+ ```
51
+
38
52
  ### Get a store instance
39
53
 
40
54
  All usage revolves around your store, as per Vend itself
41
55
 
42
56
 
43
57
  ```ruby
44
- store = Vend::Store.new('store_name', 'user_name', 'password')
58
+ # Create an instance of your store with Basic Auth
59
+ store = Vend::Store.new({:store_name => 'store_name', :username => 'user_name', :password => 'password'})
60
+ #Or Create an instance of your store with OAuth
61
+ store = Vend::Store.new({:store_name => 'store_name', :auth_token => 'auth_token'})
45
62
  ```
46
63
 
47
64
  Once you have a store instance you can retrieve your objects
@@ -114,6 +131,28 @@ product.save!
114
131
  => true
115
132
  ```
116
133
 
134
+ #### Creating a Product Variant
135
+
136
+ Product variants have the same `handle` as another product, but a different `sku`. You can create a variant of a product easily with the `#build_variant`, `#create_variant` and `#create_variant!` methods.
137
+
138
+ Underneath the hood, it's simply copying attributes to a new instance, then changing the `sku` to either a provided new sku, or appending an incrementing integer to an existing `sku`.
139
+
140
+ ```ruby
141
+ product.sku = 'my-product'
142
+ product.build_variant(sku: 'my-product-alt')
143
+ => #<Vend::Product>
144
+
145
+ product.build_variant(sku: 'my-product-alt').sku
146
+ => 'my-product-alt'
147
+
148
+ product.build_variant.sku
149
+ => 'my-product-1'
150
+
151
+ product.sku = 'my-product-3'
152
+ product.build_variant.sku
153
+ => 'my-product-4'
154
+ ```
155
+
117
156
  ### Register Sales
118
157
 
119
158
  ```ruby
@@ -136,6 +175,18 @@ store.registers.map &:name
136
175
  => ["Main Register", "Back office Register"]
137
176
  ```
138
177
 
178
+ #### Open register
179
+
180
+ ```ruby
181
+ store.registers.first.open!
182
+ ```
183
+
184
+ #### Close register
185
+
186
+ ```ruby
187
+ store.registers.first.close!
188
+ ```
189
+
139
190
  ### Suppliers
140
191
 
141
192
  ```ruby
@@ -164,12 +215,25 @@ store.users.map &:name
164
215
  => ["A cashier", "Mal Curtis", "Joe Bloggs"]
165
216
  ```
166
217
 
218
+ ## Tips
219
+
220
+ ### Figuring out what attributes a resource has
221
+ Want to know what attributes are on a particular resource? Use `#attributes`. Vending Machine will map all returned attributes to a resource, only a portion of which are defined in the resource’s code (for validation and type coercion).
222
+
223
+ ```ruby
224
+ store.taxes.first.attributes
225
+ => {:id=>"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
226
+ :rate=>0.15,
227
+ :default=>true,
228
+ :name=>"NZ GST"}
229
+ ```
230
+
167
231
  ## Status
168
232
  * COMPLETE: GET index resources are implemented, with the exception of Stock Control
169
233
  * IN PROGRESS: find singular resources `store.products.find('some_id')`
170
234
  * IN PROGRESS: create register sales `store.sale.create products: [product1, product2]`
171
235
  * COMPLETE: create products
172
- * IN PROGRESS: Create Product Variants (This seems to happen when posting a new product with a same handle, but different sku)
236
+ * COMPLETE: Create Product Variants (This seems to happen when posting a new product with a same handle, but different sku)
173
237
  * TODO: Delete resources
174
238
  * TODO: Scopes for Customer and Register Sales
175
239
 
@@ -2,6 +2,7 @@ $: << File.expand_path(File.dirname(__FILE__))
2
2
  %w{
3
3
  version
4
4
  errors
5
+ config
5
6
 
6
7
  modules/declarative_setters
7
8
  modules/finders
@@ -42,5 +43,13 @@ module Vend
42
43
  def domain
43
44
  @domain || "vendhq.com"
44
45
  end
46
+
47
+ def config(&block)
48
+ if block_given?
49
+ block.call(Vend::Config)
50
+ else
51
+ Vend::Config
52
+ end
53
+ end
45
54
  end
46
55
  end
@@ -0,0 +1,22 @@
1
+ module Vend
2
+ module Config
3
+ class << self
4
+
5
+ VALID_AUTHENTICATION_METHODS = %i(basic_auth oauth)
6
+ DEFAULT_AUTHENTICATION_METHOD = :basic_auth
7
+
8
+ def auth_method=(method)
9
+ if VALID_AUTHENTICATION_METHODS.include?(method.to_sym)
10
+ @auth_method = method.to_sym
11
+ else
12
+ raise Vend::InvalidConfig("%s is not a valid authentication method" % method)
13
+ end
14
+ end
15
+
16
+ def auth_method
17
+ @auth_method || DEFAULT_AUTHENTICATION_METHOD
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -9,4 +9,6 @@ module Vend
9
9
 
10
10
  class ServerError < Error; end
11
11
 
12
+ class InvalidConfig < Error; end
13
+
12
14
  end
@@ -31,6 +31,14 @@ module Vend::Paths
31
31
  [ self.class.collection_api_path, id ].compact.join("/")
32
32
  end
33
33
 
34
+ def close_path
35
+ [ self.class.collection_api_path, id, 'close' ].compact.join("/")
36
+ end
37
+
38
+ def open_path
39
+ [ self.class.collection_api_path, id, 'open' ].compact.join("/")
40
+ end
41
+
34
42
  def self.included(base)
35
43
  base.extend(ClassMethods)
36
44
  end
@@ -18,7 +18,7 @@ module Vend
18
18
 
19
19
  def save!
20
20
  save_path = id ? update_path : self.class.create_path
21
- method = id ? :put : :post
21
+ method = id ? :post : :post
22
22
  response = store.send(method, path: save_path,
23
23
  data: sendable_attributes.to_json,
24
24
  status: 200
@@ -41,6 +41,8 @@ module Vend
41
41
  self
42
42
  end
43
43
 
44
+
45
+
44
46
  private
45
47
 
46
48
  def sendable_attributes
@@ -59,7 +59,26 @@ module Vend
59
59
  end
60
60
 
61
61
  def remote_records
62
- http_response.data.first.last
62
+ # Is there pagination info?
63
+ pagination = http_response.data["pagination"]
64
+
65
+ if pagination
66
+ # Get all pages
67
+ data = []
68
+ page = 1
69
+ pages = pagination["pages"]
70
+ while page <= pages
71
+ http_response.data.delete("pagination")
72
+ data.concat(http_response.data.first.last)
73
+ @_http_response = nil
74
+ page += 1
75
+ (@parameters ||= {})[:page] = page
76
+ end
77
+ @parameters.delete(:page)
78
+ data
79
+ else
80
+ http_response.data.first.last
81
+ end
63
82
  end
64
83
 
65
84
  def records
@@ -74,3 +93,4 @@ module Vend
74
93
  end
75
94
  end
76
95
  end
96
+
@@ -5,5 +5,23 @@ module Vend
5
5
  attribute :register_close_time, DateTime
6
6
  attribute :register_open_time, DateTime
7
7
  attribute :register_open_count_sequence, Integer
8
+
9
+ # Close register
10
+ def close!
11
+ self.attributes = store.post(
12
+ path: close_path,
13
+ status: 200
14
+ ).data
15
+ self
16
+ end
17
+
18
+ # Open register
19
+ def open!
20
+ self.attributes = store.post(
21
+ path: open_path,
22
+ status: 200
23
+ ).data
24
+ self
25
+ end
8
26
  end
9
27
  end
@@ -6,8 +6,14 @@ module Vend
6
6
  class Store
7
7
  include HasResources
8
8
 
9
- def initialize name, username, password
10
- @name, @credentials = name, [ username, password ]
9
+ def initialize(credentials={})
10
+ @authenticator = Vend::Config.auth_method
11
+ case @authenticator
12
+ when :basic_auth
13
+ @name, @credentials = credentials[:store_name], [credentials[:username], credentials[:password]]
14
+ when :oauth
15
+ @name, @auth_token = credentials[:store_name], credentials[:auth_token]
16
+ end
11
17
  end
12
18
 
13
19
  ##
@@ -47,6 +53,7 @@ module Vend
47
53
  response.headers,
48
54
  response.body
49
55
  )
56
+
50
57
  end
51
58
 
52
59
  ##
@@ -95,7 +102,12 @@ module Vend
95
102
  @_faraday ||= Faraday.new(url) do |conn|
96
103
  conn.request :json
97
104
  conn.response :json
98
- conn.basic_auth *@credentials
105
+ case @authenticator
106
+ when :basic_auth
107
+ conn.basic_auth *@credentials
108
+ when :oauth
109
+ conn.authorization :Bearer, @auth_token
110
+ end
99
111
  conn.adapter Faraday.default_adapter
100
112
  end
101
113
  end
@@ -1,3 +1,3 @@
1
1
  module Vend
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -4,18 +4,28 @@ module Vend
4
4
  describe Store do
5
5
  describe "#url" do
6
6
  it "should be the store api endpoint" do
7
- store = Vend::Store.new('test-store', :a, :a)
7
+ store = Vend::Store.new({:store_name => 'test-store', :username => :a, :password => :a})
8
8
  store.send(:url).must_equal "https://test-store.vendhq.com/api"
9
9
  end
10
10
  end
11
11
 
12
- describe "#faraday" do
12
+ describe "#faraday with basic auth" do
13
13
  it "should be an authorized Faraday client" do
14
- store = Vend::Store.new('test-store', "abc", "123")
14
+ store = Vend::Store.new({:store_name => 'test-store', :username => 'abc', :password => '123'})
15
15
  conn = store.send(:faraday)
16
16
  assert auth = conn.headers['Authorization']
17
17
  assert_equal Faraday::Request::BasicAuthentication.header("abc", "123"), auth
18
18
  end
19
19
  end
20
+
21
+ describe "#faraday with oauth" do
22
+ it "should be an authorized Faraday client" do
23
+ Vend::Config.auth_method = :oauth
24
+ store = Vend::Store.new({:store_name => 'test-store', :auth_token => 'my-dummy-token'})
25
+ conn = store.send(:faraday)
26
+ assert auth = conn.headers['Authorization']
27
+ assert_equal Faraday::Request::Authorization.header("Bearer", "my-dummy-token"), auth
28
+ end
29
+ end
20
30
  end
21
31
  end
metadata CHANGED
@@ -1,158 +1,139 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vending-machine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
5
- prerelease:
4
+ version: 0.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Mal Curtis
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-12-16 00:00:00.000000000 Z
11
+ date: 2014-08-20 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: faraday
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: faraday_middleware
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: addressable
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - ">="
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: virtus
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ~>
59
+ - - "~>"
68
60
  - !ruby/object:Gem::Version
69
61
  version: 0.5.3
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ~>
66
+ - - "~>"
76
67
  - !ruby/object:Gem::Version
77
68
  version: 0.5.3
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: minitest
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - ">="
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - ">="
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: ansi
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
- - - ! '>='
87
+ - - ">="
100
88
  - !ruby/object:Gem::Version
101
89
  version: '0'
102
90
  type: :development
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
- - - ! '>='
94
+ - - ">="
108
95
  - !ruby/object:Gem::Version
109
96
  version: '0'
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: turn
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
- - - ! '>='
101
+ - - ">="
116
102
  - !ruby/object:Gem::Version
117
103
  version: '0'
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
- - - ! '>='
108
+ - - ">="
124
109
  - !ruby/object:Gem::Version
125
110
  version: '0'
126
111
  - !ruby/object:Gem::Dependency
127
112
  name: rake
128
113
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
114
  requirements:
131
- - - ! '>='
115
+ - - ">="
132
116
  - !ruby/object:Gem::Version
133
117
  version: '0'
134
118
  type: :development
135
119
  prerelease: false
136
120
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
121
  requirements:
139
- - - ! '>='
122
+ - - ">="
140
123
  - !ruby/object:Gem::Version
141
124
  version: '0'
142
125
  - !ruby/object:Gem::Dependency
143
126
  name: webmock
144
127
  requirement: !ruby/object:Gem::Requirement
145
- none: false
146
128
  requirements:
147
- - - ! '>='
129
+ - - ">="
148
130
  - !ruby/object:Gem::Version
149
131
  version: '0'
150
132
  type: :development
151
133
  prerelease: false
152
134
  version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
135
  requirements:
155
- - - ! '>='
136
+ - - ">="
156
137
  - !ruby/object:Gem::Version
157
138
  version: '0'
158
139
  description: Client for the Vend API
@@ -162,12 +143,14 @@ executables: []
162
143
  extensions: []
163
144
  extra_rdoc_files: []
164
145
  files:
165
- - .gitignore
146
+ - ".gitignore"
147
+ - ".rspec"
166
148
  - Gemfile
167
149
  - LICENSE
168
150
  - README.md
169
151
  - Rakefile
170
152
  - lib/vend.rb
153
+ - lib/vend/config.rb
171
154
  - lib/vend/errors.rb
172
155
  - lib/vend/has_resources.rb
173
156
  - lib/vend/modules/declarative_setters.rb
@@ -205,27 +188,26 @@ files:
205
188
  - vending-machine.gemspec
206
189
  homepage: https://github.com/snikch/vending-machine
207
190
  licenses: []
191
+ metadata: {}
208
192
  post_install_message:
209
193
  rdoc_options: []
210
194
  require_paths:
211
195
  - lib
212
196
  required_ruby_version: !ruby/object:Gem::Requirement
213
- none: false
214
197
  requirements:
215
- - - ! '>='
198
+ - - ">="
216
199
  - !ruby/object:Gem::Version
217
200
  version: '0'
218
201
  required_rubygems_version: !ruby/object:Gem::Requirement
219
- none: false
220
202
  requirements:
221
- - - ! '>='
203
+ - - ">="
222
204
  - !ruby/object:Gem::Version
223
205
  version: '0'
224
206
  requirements: []
225
207
  rubyforge_project:
226
- rubygems_version: 1.8.23
208
+ rubygems_version: 2.2.2
227
209
  signing_key:
228
- specification_version: 3
210
+ specification_version: 4
229
211
  summary: Exposes the Vend API as an object model
230
212
  test_files:
231
213
  - spec/resource_spec.rb
@@ -234,4 +216,3 @@ test_files:
234
216
  - spec/store_spec.rb
235
217
  - spec/support/url_assertions.rb
236
218
  - spec/support/webmock.rb
237
- has_rdoc: