springboard-retail 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/.yardopts +1 -0
  6. data/Gemfile +14 -0
  7. data/Gemfile.lock +66 -0
  8. data/LICENSE +21 -0
  9. data/README.md +253 -0
  10. data/Rakefile +16 -0
  11. data/lib/springboard-retail.rb +1 -0
  12. data/lib/springboard/client.rb +263 -0
  13. data/lib/springboard/client/body.rb +12 -0
  14. data/lib/springboard/client/collection.rb +108 -0
  15. data/lib/springboard/client/errors.rb +17 -0
  16. data/lib/springboard/client/resource.rb +205 -0
  17. data/lib/springboard/client/response.rb +85 -0
  18. data/lib/springboard/client/uri_ext.rb +51 -0
  19. data/spec/shared_client_context.rb +5 -0
  20. data/spec/spec_helper.rb +12 -0
  21. data/spec/springboard/client/body_spec.rb +32 -0
  22. data/spec/springboard/client/resource_spec.rb +250 -0
  23. data/spec/springboard/client/response_spec.rb +100 -0
  24. data/spec/springboard/client/uri_ext_spec.rb +51 -0
  25. data/spec/springboard/client_spec.rb +214 -0
  26. data/springboard-retail.gemspec +20 -0
  27. data/vendor/cache/addressable-2.2.8.gem +0 -0
  28. data/vendor/cache/coderay-1.0.7.gem +0 -0
  29. data/vendor/cache/coveralls-0.6.9.gem +0 -0
  30. data/vendor/cache/crack-0.3.1.gem +0 -0
  31. data/vendor/cache/diff-lcs-1.1.3.gem +0 -0
  32. data/vendor/cache/hashie-2.0.5.gem +0 -0
  33. data/vendor/cache/json-1.8.1.gem +0 -0
  34. data/vendor/cache/method_source-0.8.gem +0 -0
  35. data/vendor/cache/mime-types-1.25.gem +0 -0
  36. data/vendor/cache/multi_json-1.8.0.gem +0 -0
  37. data/vendor/cache/patron-0.4.18.gem +0 -0
  38. data/vendor/cache/pry-0.9.10.gem +0 -0
  39. data/vendor/cache/rake-0.9.2.2.gem +0 -0
  40. data/vendor/cache/rest-client-1.6.7.gem +0 -0
  41. data/vendor/cache/rspec-2.11.0.gem +0 -0
  42. data/vendor/cache/rspec-core-2.11.1.gem +0 -0
  43. data/vendor/cache/rspec-expectations-2.11.2.gem +0 -0
  44. data/vendor/cache/rspec-mocks-2.11.1.gem +0 -0
  45. data/vendor/cache/simplecov-0.7.1.gem +0 -0
  46. data/vendor/cache/simplecov-html-0.7.1.gem +0 -0
  47. data/vendor/cache/slop-3.3.2.gem +0 -0
  48. data/vendor/cache/term-ansicolor-1.2.2.gem +0 -0
  49. data/vendor/cache/thor-0.18.1.gem +0 -0
  50. data/vendor/cache/tins-0.9.0.gem +0 -0
  51. data/vendor/cache/webmock-1.8.8.gem +0 -0
  52. metadata +148 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 87e9ec06faad25bd8e8039f40af91e2152eeebdc
4
+ data.tar.gz: 97c4703a8894e57572c4a3f9cd8decae97951f8f
5
+ SHA512:
6
+ metadata.gz: 0396c1a84ffc53e91424bec9fb7c095cd9ba5e955c7339d900e5fb488faeea1146cec6de0ca5c3cab74bf3bc9fd6b189596c875e20d469e312af8f0b418dd7dd
7
+ data.tar.gz: 65d39bd20a9206d286820502a205309fc15d8228711e2a79ce6b9f316659449aa2611475f5e9d9e7ba23e2a3cb71abda94f4c211d74bff90083afaba02a0feb0
@@ -0,0 +1,4 @@
1
+ pkg
2
+ .yardoc
3
+ doc
4
+ coverage
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ bundler_args: --without development
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
@@ -0,0 +1 @@
1
+ --title "Springboard Client"
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rake'
7
+ gem 'rspec', '~> 2.11'
8
+ gem 'webmock', :require => false
9
+ gem 'coveralls', :require => false
10
+ end
11
+
12
+ group :development do
13
+ gem 'pry'
14
+ end
@@ -0,0 +1,66 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ springboard-retail (4.0.0)
5
+ addressable (>= 2.2.8)
6
+ hashie
7
+ json (>= 1.7.4)
8
+ patron (>= 0.4.18)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ addressable (2.2.8)
14
+ coderay (1.0.7)
15
+ coveralls (0.6.9)
16
+ multi_json (~> 1.3)
17
+ rest-client
18
+ simplecov (>= 0.7)
19
+ term-ansicolor
20
+ thor
21
+ crack (0.3.1)
22
+ diff-lcs (1.1.3)
23
+ hashie (2.0.5)
24
+ json (1.8.1)
25
+ method_source (0.8)
26
+ mime-types (1.25)
27
+ multi_json (1.8.0)
28
+ patron (0.4.18)
29
+ pry (0.9.10)
30
+ coderay (~> 1.0.5)
31
+ method_source (~> 0.8)
32
+ slop (~> 3.3.1)
33
+ rake (0.9.2.2)
34
+ rest-client (1.6.7)
35
+ mime-types (>= 1.16)
36
+ rspec (2.11.0)
37
+ rspec-core (~> 2.11.0)
38
+ rspec-expectations (~> 2.11.0)
39
+ rspec-mocks (~> 2.11.0)
40
+ rspec-core (2.11.1)
41
+ rspec-expectations (2.11.2)
42
+ diff-lcs (~> 1.1.3)
43
+ rspec-mocks (2.11.1)
44
+ simplecov (0.7.1)
45
+ multi_json (~> 1.0)
46
+ simplecov-html (~> 0.7.1)
47
+ simplecov-html (0.7.1)
48
+ slop (3.3.2)
49
+ term-ansicolor (1.2.2)
50
+ tins (~> 0.8)
51
+ thor (0.18.1)
52
+ tins (0.9.0)
53
+ webmock (1.8.8)
54
+ addressable (~> 2.2.8)
55
+ crack (>= 0.1.7)
56
+
57
+ PLATFORMS
58
+ ruby
59
+
60
+ DEPENDENCIES
61
+ coveralls
62
+ pry
63
+ rake
64
+ rspec (~> 2.11)
65
+ springboard-retail!
66
+ webmock
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Springboard Retail
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,253 @@
1
+ # Springboard Retail Client
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/springboard-retail.png)](http://badge.fury.io/rb/springboard-retail)
4
+ [![Build Status](https://travis-ci.org/springboardretail/springboard-client-ruby.png?branch=master)](https://travis-ci.org/springboardretail/springboard-client-ruby)
5
+ [![Code Climate](https://codeclimate.com/github/springboardretail/springboard-client-ruby.png)](https://codeclimate.com/github/springboardretail/springboard-client-ruby)
6
+ [![Coverage Status](https://coveralls.io/repos/springboardretail/springboard-client-ruby/badge.png)](https://coveralls.io/r/springboardretail/springboard-client-ruby)
7
+ [![Dependency Status](https://gemnasium.com/springboardretail/springboard-client-ruby.png)](https://gemnasium.com/springboardretail/springboard-client-ruby)
8
+
9
+ This is the [Springboard Retail](http://springboardretail.com/) (a point-of-sale/retail management system) client library for Ruby. It provides access to the Springboard Retail HTTP API.
10
+
11
+ It is a wrapper around the [Patron](http://toland.github.com/patron/) HTTP client library. Supports MRI 1.9+.
12
+
13
+ You can find [documentation here](http://rdoc.info/github/springboard/springboard-client-ruby).
14
+
15
+ ## Installation
16
+
17
+ You need a recent version of libcurl and a sane build environment.
18
+
19
+ Debian/Ubuntu:
20
+
21
+ ```
22
+ sudo apt-get install build-essential libcurl4-openssl-dev
23
+ gem install springboard-client
24
+ ```
25
+
26
+ ## Connecting
27
+
28
+ ```ruby
29
+ springboard = Springboard::Client.new 'http://example.springboard.us/api'
30
+ springboard.auth :username => 'user', :password => 'secret'
31
+ ```
32
+
33
+ ## Resource oriented
34
+
35
+ ```ruby
36
+ resource = springboard[:items][1234]
37
+ response = resource.get
38
+ response = resource.delete
39
+
40
+ # Query string generation:
41
+ resource1 = springboard[:items]
42
+ resource2 = resource.query(:key1 => 'val1', 'key with spaces' => 'val with spaces')
43
+ resource2.uri.to_s
44
+ # => "/items?key%20with%20spaces=val%20with%20spaces&key1=val1"
45
+ ```
46
+
47
+ ## URI oriented
48
+
49
+ ```ruby
50
+ response = springboard.get '/items/1234'
51
+ response = springboard.delete '/items/1234'
52
+ item_count = springboard.count '/items'
53
+ ```
54
+
55
+ ## Collection Resources
56
+
57
+ ### Enumerable
58
+ Resources include Ruby's Enumerable module for easy iteration over collections:
59
+
60
+ ```ruby
61
+ springboard[:items].each do |item|
62
+ puts item['description']
63
+ end
64
+
65
+ item_count = springboard[:items].count
66
+
67
+ usernames = springboard[:users].map {|user| user['login']}
68
+ ```
69
+
70
+ ### Filtering
71
+ Resources have a `filter` method that support's Springboard's advanced filter syntax:
72
+
73
+ ```ruby
74
+ active_users = springboard[:users].filter(:active => true)
75
+ active_users.each do |user|
76
+ # do something with each active user
77
+ end
78
+
79
+ # filter returns a new resource which allows for chaining:
80
+ items = springboard[:items]
81
+ active_items = items.filter(:active => true)
82
+ active_items.filter(:price => {'$gt' => 10}).each do |item|
83
+ # ...
84
+ end
85
+
86
+ # filtering custom fields:
87
+ springboard[:items].filter('custom@size'=> 'XL')
88
+ ```
89
+
90
+ ### Sorting
91
+ Resources have a `sort` method that accepts any number of sort options. Note that each call to sort overwrites any previous sorts.
92
+
93
+ ```ruby
94
+ resource.sort(:id, :price)
95
+ resource.sort('created_at,desc')
96
+
97
+ # returns a new resource for chaining:
98
+ resource.sort(:description, :created_at).filter(:active => true).each do |item|
99
+ # ...
100
+ end
101
+ ```
102
+
103
+ ### Creating Resources
104
+
105
+ Create a new resource via POST:
106
+
107
+ ```ruby
108
+ collection = client[:items]
109
+ response = collection.post! :description => 'Some New Item'
110
+ response.status_line
111
+ # => "HTTP/1.1 201 Created"
112
+
113
+ # To fetch the newly created resource:
114
+ new_item_response = response.resource.get!
115
+ new_item_response[:description]
116
+ # => "Some New Item"
117
+ ```
118
+
119
+ ### Embedding Related Resources
120
+
121
+ Use the `embed` method to include the contents of related resource in the response body of each item in the collection:
122
+
123
+ ```ruby
124
+ collection = client[:sales][:orders].embed(:customer, :location)
125
+ collection.first.to_hash
126
+ # => {
127
+ "id" => 1,
128
+ "customer_id" => 2,
129
+ "customer" => {
130
+ # customer data
131
+ },
132
+ "location_id" => 3,
133
+ "location" => {
134
+ # location data
135
+ }
136
+ }
137
+ ```
138
+
139
+ The `embed` method accepts one or more arguments as symbols or strings. It supports chaining and will merge the results of multiple calls.
140
+
141
+ ### Looping while results exist
142
+
143
+ Issuing deletes while iterating over a collection resource can cause the pagination to shift resulting in unexpected behavior. Use `while_results` when you want to:
144
+
145
+ * Consume messages from a queue, deleting each message after it has been processed.
146
+ * Delete all resources in a collection that doesn't support a top-level DELETE method.
147
+
148
+ For example:
149
+
150
+ ```ruby
151
+ collection = client[:system][:messages]
152
+ collection.while_results do |message|
153
+ # process message here...
154
+ collection[message['id']].delete!
155
+ end
156
+ ```
157
+
158
+ ## Request body
159
+
160
+ If the request body is a Hash, it will automatically be serialized as JSON. Otherwise, it is
161
+ passed through untouched:
162
+
163
+ ```ruby
164
+ # this:
165
+ springboard[:some_collection].post :a => 1, :b => 2
166
+
167
+ # is equivalent to this:
168
+ springboard[:some_collection].post '{"a":1,"b":2}'
169
+ ```
170
+
171
+ ## Response
172
+
173
+ ```ruby
174
+ response = springboard[:items][1].get
175
+
176
+ response.status # Response status code as an Integer
177
+ response.success? # true/false depending on whether 'status' indicates non-error
178
+ response.body # Returns a Springboard::Client::Body object (see below)
179
+ response.raw_body # Returns the raw response body as a string
180
+ response[:some_key] # Returns the corresponding key from 'body'
181
+ response.headers # Response headers as a Hash
182
+ response.resource # Returns a Resource if the response included a "Location" header, else nil
183
+ ```
184
+
185
+ ### Response Body
186
+
187
+ Given the following JSON response from the server:
188
+
189
+ ```javascript
190
+ {
191
+ "id": 1234,
192
+ "custom": {
193
+ "color": "Blue"
194
+ }
195
+ }
196
+ ```
197
+
198
+ Here are the various ways you can access the data:
199
+
200
+ ```ruby
201
+ body = response.body
202
+
203
+ # Symbols and strings can be used interchangeably for keys
204
+ body[:id]
205
+ # => 1234
206
+
207
+ body[:custom][:color]
208
+ # => "Blue"
209
+
210
+ body['custom']['color']
211
+ # => "Blue"
212
+
213
+ body.to_hash
214
+ # => {"id"=>1234, "custom"=>{"color"=>"Blue"}}
215
+
216
+ response.raw_body
217
+ # => "{\"id\":1234,\"custom\":{\"color\":\"Blue\"}}"
218
+ ```
219
+
220
+ ## Bang variants
221
+
222
+ All HTTP request methods have a bang variant that raises an exception on failure:
223
+
224
+ ```ruby
225
+ response = springboard[:i_dont_exist].get
226
+ response.status
227
+ # => 404
228
+
229
+ springboard[:i_dont_exist].get!
230
+ # Raises Springboard::Client::RequestFailed exception
231
+
232
+ # To access the response from the exception:
233
+ begin
234
+ springboard[:i_dont_exist].get!
235
+ rescue Springboard::Client::RequestFailed => error
236
+ puts error.response.status
237
+ end
238
+ # => 404
239
+
240
+ ```
241
+
242
+ ## Debugging
243
+
244
+ ```ruby
245
+ # Log request/response trace to stdout
246
+ client.debug = true
247
+
248
+ # Or, log to a file
249
+ client.debug = '/path/to/file.log'
250
+
251
+ # Same values can be passed via :debug option to client constructor
252
+ client = Springboard::Client.new '<url>', :debug => true
253
+ ```
@@ -0,0 +1,16 @@
1
+ require 'bundler/setup'
2
+ Bundler.require(:default, :development)
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
9
+
10
+ desc "Start a console with a Springboard::Client instance"
11
+ task :console do
12
+ require 'springboard/client'
13
+ CLIENT = Springboard::Client.new(ENV['URI'])
14
+ CLIENT.auth :username => ENV['USER'], :password => ENV['PASSWORD']
15
+ Pry.start
16
+ end
@@ -0,0 +1 @@
1
+ require 'springboard/client'
@@ -0,0 +1,263 @@
1
+ require 'rubygems'
2
+ require 'patron'
3
+ require 'addressable/uri'
4
+ require 'json'
5
+
6
+ require 'springboard/client/errors'
7
+
8
+ ##
9
+ # Springboard namespace
10
+ module Springboard
11
+ ##
12
+ # The main point of interaction for the Springboard Client library.
13
+ #
14
+ # Client code must successfully authenticate with the API via the {#auth}
15
+ # method before calling any HTTP methods or the API will return authorization
16
+ # errors.
17
+ #
18
+ # Provides direct access to the URI-oriented interface via the HTTP methods.
19
+ # Provides access to the URI-oriented interface via the {#[]} method.
20
+ class Client
21
+ ##
22
+ # Alias for {Addressable::URI}
23
+ URI = Addressable::URI
24
+
25
+ ##
26
+ # Default number of records per page when iterating over collection resources
27
+ DEFAULT_PER_PAGE = 20
28
+
29
+ ##
30
+ # Default request timeout in seconds
31
+ DEFAULT_TIMEOUT = 60
32
+
33
+ ##
34
+ # Default connection timeout in seconds
35
+ DEFAULT_CONNECT_TIMEOUT = 10
36
+
37
+ ##
38
+ # @return [Addressable::URI] The client's base URI
39
+ attr_reader :base_uri
40
+
41
+ ##
42
+ # @param [String] base_uri Base URI
43
+ # @option opts [Boolean, String] :debug Pass true to debug to stdout. Pass a String to debug to given filename.
44
+ # @option opts [Boolean] :insecure Disable SSL certificate verification
45
+ def initialize(base_uri, opts={})
46
+ @base_uri = URI.parse(base_uri)
47
+ configure_session(base_uri, opts)
48
+ end
49
+
50
+ ##
51
+ # Returns the underlying Patron session
52
+ #
53
+ # @see http://patron.rubyforge.org/Patron/Session.html Patron::Session docs
54
+ #
55
+ # @return [Patron::Session]
56
+ def session
57
+ @session ||= Patron::Session.new
58
+ end
59
+
60
+ ##
61
+ # Set to true to enable debugging to STDOUT or a string to write to the file
62
+ # at that path.
63
+ #
64
+ # @param [String, Boolean] debug
65
+ #
66
+ # @return [String, Boolean] The debug argument
67
+ def debug=(debug)
68
+ session.enable_debug(debug == true ? nil : debug)
69
+ end
70
+
71
+ ##
72
+ # Passes the given credentials to the server, storing the session token on success.
73
+ #
74
+ # @raise [AuthFailed] If the credentials were invalid or the server returned an error
75
+ #
76
+ # @return [true]
77
+ #
78
+ # @option opts [String] :username Springboard username
79
+ # @option opts [String] :password Springboard password
80
+ def auth(opts={})
81
+ unless opts[:username] && opts[:password]
82
+ raise "Must specify :username and :password"
83
+ end
84
+ body = URI.form_encode \
85
+ :auth_key => opts[:username],
86
+ :password => opts[:password]
87
+ response = post '/auth/identity/callback', body,
88
+ 'Content-Type' => 'application/x-www-form-urlencoded'
89
+ response.success? or raise AuthFailed, "Springboard auth failed"
90
+ end
91
+
92
+ ##
93
+ # Performs a HEAD request against the given URI and returns the {Response}.
94
+ #
95
+ # @return [Response]
96
+ def head(uri, headers=false); make_request(:head, uri, headers); end
97
+
98
+ ##
99
+ # Performs a HEAD request against the given URI. Returns the {Response}
100
+ # on success and raises a {RequestFailed} on failure.
101
+ #
102
+ # @raise [RequestFailed] On error response
103
+ #
104
+ # @return [Response]
105
+ def head!(uri, headers=false); raise_on_fail head(uri, headers); end
106
+
107
+ ##
108
+ # Performs a GET request against the given URI and returns the {Response}.
109
+ #
110
+ # @return [Response]
111
+ def get(uri, headers=false); make_request(:get, uri, headers); end
112
+
113
+ ##
114
+ # Performs a GET request against the given URI. Returns the {Response}
115
+ # on success and raises a {RequestFailed} on failure.
116
+ #
117
+ # @raise [RequestFailed] On error response
118
+ #
119
+ # @return [Response]
120
+ def get!(uri, headers=false); raise_on_fail get(uri, headers); end
121
+
122
+ ##
123
+ # Performs a DELETE request against the given URI and returns the {Response}.
124
+ #
125
+ # @return [Response]
126
+ def delete(uri, headers=false); make_request(:delete, uri, headers); end
127
+
128
+ ##
129
+ # Performs a DELETE request against the given URI. Returns the {Response}
130
+ # on success and raises a {RequestFailed} on failure.
131
+ #
132
+ # @raise [RequestFailed] On error response
133
+ #
134
+ # @return [Response]
135
+ def delete!(uri, headers=false); raise_on_fail delete(uri, headers); end
136
+
137
+ ##
138
+ # Performs a PUT request against the given URI and returns the {Response}.
139
+ #
140
+ # @return [Response]
141
+ def put(uri, body, headers=false); make_request(:put, uri, headers, body); end
142
+
143
+ ##
144
+ # Performs a PUT request against the given URI. Returns the {Response}
145
+ # on success and raises a {RequestFailed} on failure.
146
+ #
147
+ # @raise [RequestFailed] On error response
148
+ #
149
+ # @return [Response]
150
+ def put!(uri, body, headers=false); raise_on_fail put(uri, body, headers); end
151
+
152
+ ##
153
+ # Performs a POST request against the given URI and returns the {Response}.
154
+ #
155
+ # @return [Response]
156
+ def post(uri, body, headers=false); make_request(:post, uri, headers, body); end
157
+
158
+ ##
159
+ # Performs a POST request against the given URI. Returns the {Response}
160
+ # on success and raises a {RequestFailed} on failure.
161
+ #
162
+ # @raise [RequestFailed] On error response
163
+ #
164
+ # @return [Response]
165
+ def post!(uri, body, headers=false); raise_on_fail post(uri, body, headers); end
166
+
167
+ ##
168
+ # Returns a Resource for the given URI path.
169
+ #
170
+ # @return [Resource]
171
+ def [](uri)
172
+ Resource.new(self, uri)
173
+ end
174
+
175
+ ##
176
+ # Iterates over each page of subordinate resources of the given collection
177
+ # resource URI and yields the {Response} to the block.
178
+ def each_page(uri)
179
+ uri = URI.parse(uri)
180
+ total_pages = nil
181
+ page = 1
182
+ uri.query_values = {'per_page' => DEFAULT_PER_PAGE}.merge(uri.query_values || {})
183
+ while total_pages.nil? or page <= total_pages
184
+ uri.merge_query_values! 'page' => page
185
+ response = get!(uri)
186
+ yield response
187
+ total_pages ||= response['pages']
188
+ page += 1
189
+ end
190
+ end
191
+
192
+ ##
193
+ # Iterates over each subordinate resource of the given collection resource
194
+ # URI and yields its representation to the given block.
195
+ def each(uri)
196
+ each_page(uri) do |page|
197
+ page['results'].each do |result|
198
+ yield result
199
+ end
200
+ end
201
+ end
202
+
203
+ ##
204
+ # Returns a count of subordinate resources of the given collection resource
205
+ # URI.
206
+ #
207
+ # @param [#to_s] uri
208
+ # @raise [RequestFailed] If the GET fails
209
+ # @return [Integer] The subordinate resource count
210
+ def count(uri)
211
+ uri = URI.parse(uri)
212
+ uri.merge_query_values! 'page' => 1, 'per_page' => 1
213
+ get!(uri)['total']
214
+ end
215
+
216
+ private
217
+
218
+ def prepare_request_body(body)
219
+ body.is_a?(Hash) ? JSON.dump(body) : body
220
+ end
221
+
222
+ def make_request(method, uri, headers=false, body=false)
223
+ args = [prepare_uri(uri).to_s]
224
+ args.push prepare_request_body(body) unless body === false
225
+ args.push headers unless headers === false
226
+ new_response session.__send__(method, *args)
227
+ end
228
+
229
+ def raise_on_fail(response)
230
+ if !response.success?
231
+ error = RequestFailed.new "Request failed with status: #{response.status_line}"
232
+ error.response = response
233
+ raise error
234
+ end
235
+ response
236
+ end
237
+
238
+ def prepare_uri(uri)
239
+ uri = URI.parse(uri)
240
+ uri.path = uri.path.gsub(/^#{base_uri.path}/, '')
241
+ uri
242
+ end
243
+
244
+ def new_response(patron_response)
245
+ Response.new patron_response, self
246
+ end
247
+
248
+ def configure_session(base_url, opts)
249
+ session.base_url = base_url
250
+ session.headers['Content-Type'] = 'application/json'
251
+ session.handle_cookies
252
+ session.insecure = opts[:insecure] if opts.has_key?(:insecure)
253
+ session.timeout = DEFAULT_TIMEOUT
254
+ session.connect_timeout = DEFAULT_CONNECT_TIMEOUT
255
+ self.debug = opts[:debug] if opts.has_key?(:debug)
256
+ end
257
+ end
258
+ end
259
+
260
+ require 'springboard/client/resource'
261
+ require 'springboard/client/response'
262
+ require 'springboard/client/body'
263
+ require 'springboard/client/uri_ext'