bootic_client 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e21ff6db54eead797a8ca1206880db8f32fd7bb2
4
- data.tar.gz: 6cd1e6710e2a4b19edf284c749094217242c53ff
3
+ metadata.gz: 44cb025e788fcf5db4f335c6714b051a970e9647
4
+ data.tar.gz: 6871584b9fc940f4117e8c841f4ac1b85588121a
5
5
  SHA512:
6
- metadata.gz: ee764305af03d550c8f6263df35b5ad0c656053dd7dffe57bfbc11713af78869e20eaf57d5cbc05574c00df947c7bf533cfc8a2276cf80a9f97106d14541ee19
7
- data.tar.gz: 9faa674657d2ad7f08155366cce46fd8af5d7c740cfcb607d43c2d9b3f0e1877c0e4c917691c95bdec8996151271dba0ed9db9765fb623a1ea5fe3974caa4e57
6
+ metadata.gz: 8d2f579c6dca54966104b03b8518a5e9b32910b4195e62c2d84fa01ead10a5c16ae5465f4ea00349e8679c30b0beb0077a8f1392c0cf0e7adb47500b2f3b73dd
7
+ data.tar.gz: f03e36499a5275ae7a999f2be58ce05ce76d54eccb79a57fdf3388fec72b2d11f38c1e1eaa5412d5277f4bafaa485cdccba3a5dceeb25895d3daa4347787b185
data/Gemfile CHANGED
@@ -4,7 +4,7 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  group :test do
7
- gem 'byebug'
7
+ gem 'byebug' if RUBY_VERSION.to_i >= 2
8
8
  gem 'vcr', '~> 2.4'
9
- gem 'webmock', '>= 1.9'
10
- end
9
+ gem 'webmock', '>= 1.20'
10
+ end
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  [![Build Status](https://travis-ci.org/bootic/bootic_client.rb.svg?branch=master)](https://travis-ci.org/bootic/bootic_client.rb)
2
2
  [![Gem Version](https://badge.fury.io/rb/bootic_client.svg)](http://badge.fury.io/rb/bootic_client)
3
3
 
4
- ## WORK IN PROGRESS
5
4
 
6
5
  # BooticClient
7
6
 
@@ -53,13 +52,41 @@ if root.has?(:all_products)
53
52
  puts product.price
54
53
  end
55
54
 
56
- if all_product.has?(:next)
55
+ # Iterate through pages of products
56
+ # See "iterating" section below for a more elegant option
57
+ if all_products.has?(:next)
57
58
  next_page = all_products.next
58
59
  next_page.each{...}
59
60
  end
60
61
  end
61
62
  ```
62
63
 
64
+ ### Iterating
65
+
66
+ Entities representing lists of things ([products](https://developers.bootic.net/rels/products/), [orders](https://developers.bootic.net/rels/orders/), etc) are fully [enumerable](http://ruby-doc.org/core-2.2.0/Enumerable.html).
67
+
68
+ ```ruby
69
+ # These will only iterate this page's worth of products
70
+ all_products.each{|pr| puts pr.title}
71
+ all_products.map(&:title)
72
+ all_products.reduce(0){|sum, pr| sum + pr.price}
73
+ ```
74
+
75
+ These lists might be part of a paginated data set. If you want to iterate items across pages and make sure you consume the full set, use `#full_set`.
76
+
77
+ ```ruby
78
+ # These will iterate all necessary pages
79
+ all_products.full_set.each{|pr| puts pr.title }
80
+ all_products.full_set.map(&:title)
81
+ all_products.full_set.first(500)
82
+ ```
83
+
84
+ You can check whether an entity is iterable with:
85
+
86
+ ```ruby
87
+ all_products.respond_to?(:each)
88
+ ```
89
+
63
90
  ## Strategies
64
91
 
65
92
  The Bootic Client supports different authentication strategies depending on the use case.
@@ -106,7 +133,6 @@ if shop.can?(:create_product)
106
133
  title: 'A shiny new product',
107
134
  price: 122332,
108
135
  status: "visible",
109
- collecton_names: ["Featured products", "Homepage"],
110
136
  variants: [
111
137
  {
112
138
  title: 'First variant',
@@ -114,6 +140,10 @@ if shop.can?(:create_product)
114
140
  available_if_no_stock: 1,
115
141
  stock: 12
116
142
  }
143
+ ],
144
+ collections: [
145
+ {title: "A new collection"},
146
+ {id: 1234}
117
147
  ]
118
148
  )
119
149
 
@@ -21,9 +21,9 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency "faraday", '~> 0.9'
22
22
  spec.add_dependency "uri_template", '~> 0.7'
23
23
  spec.add_dependency "faraday_middleware", '~> 0.9'
24
- spec.add_dependency "faraday-http-cache", '~> 0.4'
24
+ spec.add_dependency "faraday-http-cache", '0.4.2'
25
25
  spec.add_dependency "net-http-persistent", '~> 2.9'
26
- spec.add_dependency "oauth2"
26
+ spec.add_dependency "oauth2", "~> 1"
27
27
 
28
28
  spec.add_development_dependency "bundler", "~> 1.3"
29
29
  spec.add_development_dependency "rake"
@@ -2,6 +2,26 @@ require "bootic_client/relation"
2
2
  require 'ostruct'
3
3
 
4
4
  module BooticClient
5
+ module EnumerableEntity
6
+ include Enumerable
7
+
8
+ def each(&block)
9
+ self[:items].each &block
10
+ end
11
+
12
+ def full_set
13
+ page = self
14
+
15
+ Enumerator.new do |yielder|
16
+ loop do
17
+ page.each{|item| yielder.yield item }
18
+ raise StopIteration unless page.has_rel?(:next)
19
+ page = page.next
20
+ end
21
+ end
22
+ end
23
+ end
24
+
5
25
  class Entity
6
26
 
7
27
  CURIE_EXP = /(.+):(.+)/.freeze
@@ -13,10 +33,15 @@ module BooticClient
13
33
  def initialize(attrs, client, top = self)
14
34
  @attrs, @client, @top = attrs, client, top
15
35
  build!
36
+ self.extend EnumerableEntity if iterable?
37
+ end
38
+
39
+ def to_hash
40
+ @attrs
16
41
  end
17
42
 
18
43
  def [](key)
19
- properties[key.to_sym]
44
+ properties[key.to_sym] || entities[key.to_sym]
20
45
  end
21
46
 
22
47
  def has?(prop_name)
@@ -84,10 +109,6 @@ module BooticClient
84
109
  rels.has_key? prop_name.to_sym
85
110
  end
86
111
 
87
- def each(&block)
88
- iterable? ? entities[:items].each(&block) : [self].each(&block)
89
- end
90
-
91
112
  def rels
92
113
  @rels ||= (
93
114
  links = attrs.fetch('_links', {})
@@ -126,4 +147,4 @@ module BooticClient
126
147
  end
127
148
  end
128
149
  end
129
- end
150
+ end
@@ -19,6 +19,10 @@ module BooticClient
19
19
  request_and_wrap :get, config.api_root, Entity
20
20
  end
21
21
 
22
+ def from_hash(hash, wrapper_class = Entity)
23
+ wrapper_class.new hash, self
24
+ end
25
+
22
26
  def request_and_wrap(request_method, href, wrapper_class, payload = {})
23
27
  begin
24
28
  wrapper_class.new client.send(request_method, href, payload).body, self
@@ -1,3 +1,3 @@
1
1
  module BooticClient
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -144,5 +144,14 @@ describe 'BooticClient::Strategies::Authorized' do
144
144
  expect(shops.title).to eql('All shops')
145
145
  end
146
146
  end
147
+
148
+ describe '#from_hash' do
149
+ it 'builds and returns an entity' do
150
+ entity = client.from_hash('name' => 'foo', '_links' => {'delete' => {'href' => '/foo/bar'}})
151
+ expect(entity).to be_kind_of(BooticClient::Entity)
152
+ expect(entity.name).to eql('foo')
153
+ expect(entity.can?(:delete)).to be true
154
+ end
155
+ end
147
156
  end
148
157
  end
data/spec/client_spec.rb CHANGED
@@ -11,7 +11,12 @@ describe BooticClient::Client do
11
11
  {'Accept' => 'application/json', 'Authorization' => "Bearer xxx"}
12
12
  }
13
13
  let(:response_headers) {
14
- {'Content-Type' => 'application/json', 'Last-Modified' => 'Sat, 07 Jun 2014 12:10:33 GMT'}
14
+ {
15
+ 'Content-Type' => 'application/json',
16
+ 'Last-Modified' => 'Sat, 07 Jun 2014 12:10:33 GMT',
17
+ 'ETag' => '0937dafce10db7b7d405667f9576d26d',
18
+ 'Cache-Control' => 'max-age=0, private, must-revalidate'
19
+ }
15
20
  }
16
21
  let(:root_data) {
17
22
  {
@@ -57,6 +62,24 @@ describe BooticClient::Client do
57
62
  end
58
63
  end
59
64
  end
65
+
66
+ context 'and then cached by ETag' do
67
+ before do
68
+ @cached_request = stub_request(:get, root_url)
69
+ .with(headers: {'If-None-Match' => response_headers['ETag']})
70
+ .to_return(status: 304, body: '', headers: response_headers)
71
+ end
72
+
73
+ it 'returns cached response' do
74
+ r = client.get(root_url)
75
+ expect(@cached_request).to have_been_requested
76
+
77
+ expect(r.status).to eql(200)
78
+ r.body.tap do |b|
79
+ expect(b['_links']['shops']).to eql({'href' => 'https://api.bootic.net/v1/products'})
80
+ end
81
+ end
82
+ end
60
83
  end
61
84
 
62
85
  context 'errors' do
data/spec/entity_spec.rb CHANGED
@@ -67,6 +67,10 @@ describe BooticClient::Entity do
67
67
  expect(entity.page).to eql(1)
68
68
  end
69
69
 
70
+ it 'has hash access to properties' do
71
+ expect(entity[:total_items]).to eql(10)
72
+ end
73
+
70
74
  it 'wraps object properties as entities' do
71
75
  expect(entity.an_object.name).to eql('Foobar')
72
76
  expect(entity.an_object.age).to eql(22)
@@ -82,6 +86,12 @@ describe BooticClient::Entity do
82
86
  expect(entity.has?(:foobar)).to eql(false)
83
87
  end
84
88
 
89
+ describe '#to_hash' do
90
+ it 'returns original data' do
91
+ expect(entity.to_hash).to eql(list_payload)
92
+ end
93
+ end
94
+
85
95
  describe 'embedded entities' do
86
96
 
87
97
  it 'has a #entities object' do
@@ -97,6 +107,10 @@ describe BooticClient::Entity do
97
107
  end
98
108
  end
99
109
 
110
+ it 'has hash access to properties' do
111
+ expect(entity[:total_items]).to eql(10)
112
+ end
113
+
100
114
  it 'recursively builds embedded entities' do
101
115
  product = entity.items.first
102
116
  product.shop.tap do |shop|
@@ -158,17 +172,48 @@ describe BooticClient::Entity do
158
172
  end
159
173
 
160
174
  describe 'iterating' do
161
- it 'iterates items if it is a list' do
175
+ it 'is an enumerable if it is a list' do
162
176
  prods = []
163
177
  entity.each{|pr| prods << pr}
164
178
  expect(prods).to match_array(entity.items)
179
+ expect(entity.map{|pr| pr}).to match_array(entity.items)
180
+ expect(entity.reduce(0){|sum,e| sum + e.price.to_i}).to eql(24687)
181
+ expect(entity.each).to be_kind_of(Enumerator)
165
182
  end
166
183
 
167
- it 'iterates itself if not a list' do
184
+ it 'is not treated as an array if not a list' do
168
185
  ent = BooticClient::Entity.new({'foo' => 'bar'}, client)
169
- ents = []
170
- ent.each{|e| ents << e}
171
- expect(ents).to match_array([ent])
186
+ expect(ent).not_to respond_to(:each)
187
+ end
188
+ end
189
+
190
+ describe '#full_set' do
191
+ let(:page_2_data) {
192
+ {
193
+ 'total_items' => 10,
194
+ 'per_page' => 3,
195
+ 'page' => 2,
196
+ '_links' => {
197
+ 'self' => {'href' => '/foo?page=2'},
198
+ 'next' => { 'href' => '/foo?page=3'}
199
+ },
200
+ "_embedded" => {
201
+ 'items' => [
202
+ {"title" => "Item 3"},
203
+ {"title" => "Item 4"},
204
+ {"title" => "Item 5"}
205
+ ]
206
+ }
207
+ }
208
+ }
209
+ let(:page_2) { BooticClient::Entity.new(page_2_data, client) }
210
+
211
+ it 'lazily enumerates entries across pages, making as little requests as possible' do
212
+ expect(client).to receive(:request_and_wrap).with(:get, '/foo?page=2', BooticClient::Entity, {}).and_return page_2
213
+ expect(client).to_not receive(:request_and_wrap).with(:get, '/foo?page=3', BooticClient::Entity, {})
214
+ results = entity.full_set.first(4)
215
+ titles = results.map(&:title)
216
+ expect(titles).to match_array(['iPhone 4', 'iPhone 5', 'Item 3', 'Item 4'])
172
217
  end
173
218
  end
174
219
  end
metadata CHANGED
@@ -1,167 +1,167 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootic_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismael Celis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-27 00:00:00.000000000 Z
11
+ date: 2015-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0.9'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.9'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: uri_template
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0.7'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.7'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: faraday_middleware
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0.9'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.9'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: faraday-http-cache
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: '0.4'
61
+ version: 0.4.2
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: '0.4'
68
+ version: 0.4.2
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: net-http-persistent
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: '2.9'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '2.9'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: oauth2
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '1'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '1'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: bundler
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ~>
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
103
  version: '1.3'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ~>
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '1.3'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rake
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rspec
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - '>='
129
+ - - ">="
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - '>='
136
+ - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: jwt
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - '>='
143
+ - - ">="
144
144
  - !ruby/object:Gem::Version
145
145
  version: '0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - '>='
150
+ - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: dalli
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - '>='
157
+ - - ">="
158
158
  - !ruby/object:Gem::Version
159
159
  version: '0'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - '>='
164
+ - - ">="
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
167
  description: Official Ruby client for the Bootic API
@@ -171,9 +171,9 @@ executables: []
171
171
  extensions: []
172
172
  extra_rdoc_files: []
173
173
  files:
174
- - .gitignore
175
- - .rspec
176
- - .travis.yml
174
+ - ".gitignore"
175
+ - ".rspec"
176
+ - ".travis.yml"
177
177
  - Gemfile
178
178
  - LICENSE.txt
179
179
  - README.md
@@ -207,17 +207,17 @@ require_paths:
207
207
  - lib
208
208
  required_ruby_version: !ruby/object:Gem::Requirement
209
209
  requirements:
210
- - - '>='
210
+ - - ">="
211
211
  - !ruby/object:Gem::Version
212
212
  version: '0'
213
213
  required_rubygems_version: !ruby/object:Gem::Requirement
214
214
  requirements:
215
- - - '>='
215
+ - - ">="
216
216
  - !ruby/object:Gem::Version
217
217
  version: '0'
218
218
  requirements: []
219
219
  rubyforge_project:
220
- rubygems_version: 2.0.3
220
+ rubygems_version: 2.4.5
221
221
  signing_key:
222
222
  specification_version: 4
223
223
  summary: Official Ruby client for the Bootic API