tankard 0.1.0 → 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.
- checksums.yaml +4 -4
- data/.rubocop.yml +15 -0
- data/.travis.yml +41 -4
- data/CHANGELOG.md +8 -1
- data/Rakefile +3 -3
- data/lib/tankard.rb +18 -15
- data/lib/tankard/api/beer.rb +30 -39
- data/lib/tankard/api/beers.rb +15 -20
- data/lib/tankard/api/request/get.rb +13 -17
- data/lib/tankard/api/search.rb +32 -41
- data/lib/tankard/api/style.rb +19 -23
- data/lib/tankard/api/styles.rb +10 -12
- data/lib/tankard/api/utils/find.rb +15 -12
- data/lib/tankard/api/utils/page_finders.rb +42 -37
- data/lib/tankard/client.rb +10 -6
- data/lib/tankard/configuration.rb +18 -15
- data/lib/tankard/error.rb +4 -1
- data/lib/tankard/request.rb +23 -22
- data/lib/tankard/version.rb +4 -1
- data/spec/shared_examples_for_find.rb +22 -22
- data/spec/spec_helper.rb +2 -2
- data/spec/tankard/api/beer_spec.rb +113 -86
- data/spec/tankard/api/beers_spec.rb +34 -34
- data/spec/tankard/api/search_spec.rb +106 -95
- data/spec/tankard/api/style_spec.rb +102 -21
- data/spec/tankard/api/styles_spec.rb +6 -6
- data/spec/tankard/api/utils/find_spec.rb +10 -10
- data/spec/tankard/api/utils/page_finders_spec.rb +53 -50
- data/spec/tankard/client_spec.rb +42 -42
- data/spec/tankard/request_spec.rb +26 -24
- data/spec/tankard_spec.rb +21 -19
- data/tankard.gemspec +24 -22
- metadata +45 -58
data/lib/tankard/api/style.rb
CHANGED
@@ -20,9 +20,9 @@ module Tankard
|
|
20
20
|
# @param request [Tankard::Request]
|
21
21
|
# @param options [Hash]
|
22
22
|
# @return [Tankard::Api::Style]
|
23
|
-
def initialize(request, options={})
|
24
|
-
@
|
25
|
-
@
|
23
|
+
def initialize(request, options = {})
|
24
|
+
@http_client = request
|
25
|
+
@http_request_parameters = Hashie::Mash.new(options)
|
26
26
|
end
|
27
27
|
|
28
28
|
# @!method find(id_or_array, options={})
|
@@ -49,32 +49,28 @@ module Tankard
|
|
49
49
|
# @param style_id [String]
|
50
50
|
# @return [self] returns itself
|
51
51
|
def id(style_id)
|
52
|
-
@
|
52
|
+
@http_request_parameters.id = style_id
|
53
53
|
self
|
54
54
|
end
|
55
55
|
|
56
|
-
|
56
|
+
private
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
@options.delete(:id)
|
61
|
-
end
|
58
|
+
attr_reader :http_client
|
59
|
+
attr_reader :http_request_parameters
|
62
60
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
"#{route}/#{raise_if_no_id_in_options}"
|
69
|
-
end
|
61
|
+
def raise_if_no_id_in_options
|
62
|
+
@style_id = @http_request_parameters.delete(:id) if @http_request_parameters.id?
|
63
|
+
fail Tankard::Error::MissingParameter, 'No style id set' unless @style_id
|
64
|
+
@style_id
|
65
|
+
end
|
70
66
|
|
71
|
-
|
72
|
-
|
73
|
-
|
67
|
+
def route
|
68
|
+
'style'
|
69
|
+
end
|
74
70
|
|
75
|
-
|
76
|
-
|
77
|
-
|
71
|
+
def http_request_uri
|
72
|
+
"#{route}/#{raise_if_no_id_in_options}"
|
73
|
+
end
|
78
74
|
end
|
79
75
|
end
|
80
|
-
end
|
76
|
+
end
|
data/lib/tankard/api/styles.rb
CHANGED
@@ -27,22 +27,20 @@ module Tankard
|
|
27
27
|
# @param request [Tankard::Request]
|
28
28
|
# @return [Tankard::Api::Styles]
|
29
29
|
def initialize(request)
|
30
|
-
@
|
30
|
+
@http_client = request
|
31
31
|
end
|
32
32
|
|
33
|
-
|
33
|
+
private
|
34
34
|
|
35
|
-
|
36
|
-
"styles"
|
37
|
-
end
|
35
|
+
attr_reader :http_client
|
38
36
|
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
def http_request_uri
|
38
|
+
'styles'
|
39
|
+
end
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
def http_request_parameters
|
42
|
+
{}
|
43
|
+
end
|
46
44
|
end
|
47
45
|
end
|
48
|
-
end
|
46
|
+
end
|
@@ -3,10 +3,13 @@ require 'tankard/api/request/get'
|
|
3
3
|
module Tankard
|
4
4
|
module Api
|
5
5
|
module Utils
|
6
|
+
# Helper for finding one or more things by ID(s)
|
7
|
+
#
|
8
|
+
# @author Matthew Shafer
|
6
9
|
module Find
|
7
10
|
include Tankard::Api::Request::Get
|
8
11
|
|
9
|
-
def find(id_or_array, options={})
|
12
|
+
def find(id_or_array, options = {})
|
10
13
|
options = http_request_parameters.merge!(options)
|
11
14
|
|
12
15
|
if id_or_array.is_a?(Array)
|
@@ -16,20 +19,20 @@ module Tankard
|
|
16
19
|
end
|
17
20
|
end
|
18
21
|
|
19
|
-
|
22
|
+
private
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
+
def route
|
25
|
+
fail NoMethodError, 'Must implement and return the base route'
|
26
|
+
end
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
+
def http_client
|
29
|
+
fail NoMethodError, 'Must return the http object to make requests with'
|
30
|
+
end
|
28
31
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
+
def http_request_parameters
|
33
|
+
fail NoMethodError, 'Must return a hash like structure with request parameters'
|
34
|
+
end
|
32
35
|
end
|
33
36
|
end
|
34
37
|
end
|
35
|
-
end
|
38
|
+
end
|
@@ -3,6 +3,10 @@ require 'tankard/api/request/get'
|
|
3
3
|
module Tankard
|
4
4
|
module Api
|
5
5
|
module Utils
|
6
|
+
# Seamless querying of multiple pages of results
|
7
|
+
# Allows using any ruby enumerable (EX. map)
|
8
|
+
#
|
9
|
+
# @author Matthew Shafer
|
6
10
|
module PageFinders
|
7
11
|
include ::Enumerable
|
8
12
|
include Tankard::Api::Request::Get
|
@@ -11,57 +15,58 @@ module Tankard
|
|
11
15
|
#
|
12
16
|
# @yieldparam [Hash] hash containing individual beer information
|
13
17
|
def each(&block)
|
14
|
-
find_on_single_or_all_pages(
|
18
|
+
find_on_single_or_all_pages(http_request_parameters, block)
|
15
19
|
end
|
16
20
|
|
17
|
-
|
21
|
+
private
|
18
22
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
23
|
+
def find_on_single_or_all_pages(options, block)
|
24
|
+
if options[:p]
|
25
|
+
find_on_single_page(options, block)
|
26
|
+
else
|
27
|
+
find_on_all_pages(options, block)
|
25
28
|
end
|
29
|
+
end
|
26
30
|
|
27
|
-
|
28
|
-
|
31
|
+
def find_on_all_pages(options, block)
|
32
|
+
page = 0
|
29
33
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
34
|
+
loop do
|
35
|
+
page += 1
|
36
|
+
options[:p] = page if page > 1
|
37
|
+
total_pages = find_on_single_page(options, block)
|
38
|
+
break unless page < total_pages
|
35
39
|
end
|
40
|
+
end
|
36
41
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
+
def find_on_single_page(options, block)
|
43
|
+
response = get_request(http_client, http_request_uri, options)
|
44
|
+
call_block_with_data(response['data'], block)
|
45
|
+
response['numberOfPages'].to_i
|
46
|
+
end
|
42
47
|
|
43
|
-
|
44
|
-
|
48
|
+
def call_block_with_data(data, block)
|
49
|
+
fail Tankard::Error::InvalidResponse unless data
|
45
50
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
51
|
+
if data.is_a?(Hash)
|
52
|
+
block.call(data)
|
53
|
+
else
|
54
|
+
data.each { |item| block.call(item) }
|
51
55
|
end
|
56
|
+
end
|
52
57
|
|
53
|
-
|
54
|
-
|
55
|
-
|
58
|
+
def http_request_uri
|
59
|
+
fail NoMethodError, 'Need to implement method'
|
60
|
+
end
|
56
61
|
|
57
|
-
|
58
|
-
|
59
|
-
|
62
|
+
def http_client
|
63
|
+
fail NoMethodError, 'Need to implement method'
|
64
|
+
end
|
60
65
|
|
61
|
-
|
62
|
-
|
63
|
-
|
66
|
+
def http_request_parameters
|
67
|
+
fail NoMethodError, 'Need to implement method'
|
68
|
+
end
|
64
69
|
end
|
65
70
|
end
|
66
71
|
end
|
67
|
-
end
|
72
|
+
end
|
data/lib/tankard/client.rb
CHANGED
@@ -6,9 +6,13 @@ require 'tankard/api/styles'
|
|
6
6
|
require 'tankard/api/style'
|
7
7
|
|
8
8
|
module Tankard
|
9
|
+
# Interaction point for various endpoints
|
10
|
+
# When querying Tankard normally there is only one of these alive at a time
|
11
|
+
#
|
12
|
+
# @author Matthew Shafer
|
9
13
|
class Client
|
10
14
|
|
11
|
-
def initialize(options={})
|
15
|
+
def initialize(options = {})
|
12
16
|
Tankard::Configuration::KEYS.each do |key|
|
13
17
|
instance_variable_set(:"@#{key}", options[key])
|
14
18
|
end
|
@@ -16,15 +20,15 @@ module Tankard
|
|
16
20
|
@tankard_request = Tankard::Request.new(@api_key)
|
17
21
|
end
|
18
22
|
|
19
|
-
def beer(options={})
|
23
|
+
def beer(options = {})
|
20
24
|
Tankard::Api::Beer.new(@tankard_request, options)
|
21
25
|
end
|
22
26
|
|
23
|
-
def beers(options={})
|
27
|
+
def beers(options = {})
|
24
28
|
Tankard::Api::Beers.new(@tankard_request, options)
|
25
29
|
end
|
26
30
|
|
27
|
-
def search(options={})
|
31
|
+
def search(options = {})
|
28
32
|
Tankard::Api::Search.new(@tankard_request, options)
|
29
33
|
end
|
30
34
|
|
@@ -32,8 +36,8 @@ module Tankard
|
|
32
36
|
Tankard::Api::Styles.new(@tankard_request)
|
33
37
|
end
|
34
38
|
|
35
|
-
def style(options={})
|
39
|
+
def style(options = {})
|
36
40
|
Tankard::Api::Style.new(@tankard_request, options)
|
37
41
|
end
|
38
42
|
end
|
39
|
-
end
|
43
|
+
end
|
@@ -1,9 +1,12 @@
|
|
1
1
|
module Tankard
|
2
|
+
# Configuring and validating credentials
|
3
|
+
#
|
4
|
+
# @author Matthew Shafer
|
2
5
|
module Configuration
|
3
6
|
attr_writer :api_key
|
4
7
|
|
5
8
|
KEYS = [:api_key]
|
6
|
-
BREWERYDB_URL =
|
9
|
+
BREWERYDB_URL = 'http://api.brewerydb.com/v2/'
|
7
10
|
|
8
11
|
def configure
|
9
12
|
yield self
|
@@ -12,22 +15,22 @@ module Tankard
|
|
12
15
|
self
|
13
16
|
end
|
14
17
|
|
15
|
-
|
18
|
+
private
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
def credentials
|
21
|
+
{
|
22
|
+
api_key: @api_key
|
23
|
+
}
|
24
|
+
end
|
22
25
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
26
|
+
def validate_api_key!
|
27
|
+
unless @api_key.is_a?(String)
|
28
|
+
fail Tankard::Error::ConfigurationError, 'api_key is not a string'
|
27
29
|
end
|
30
|
+
end
|
28
31
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
+
def reset_client
|
33
|
+
fail Tankard::Error::ConfigurationError, 'Implement reset_client'
|
34
|
+
end
|
32
35
|
end
|
33
|
-
end
|
36
|
+
end
|
data/lib/tankard/error.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
module Tankard
|
2
|
+
# Custom errors classes
|
3
|
+
#
|
4
|
+
# @author Matthew Shafer
|
2
5
|
module Error
|
3
6
|
ConfigurationError = Class.new(::StandardError)
|
4
7
|
MissingParameter = Class.new(::StandardError)
|
@@ -7,4 +10,4 @@ module Tankard
|
|
7
10
|
InvalidResponse = Class.new(::StandardError)
|
8
11
|
ApiKeyUnauthorized = Class.new(::StandardError)
|
9
12
|
end
|
10
|
-
end
|
13
|
+
end
|
data/lib/tankard/request.rb
CHANGED
@@ -3,6 +3,9 @@ require 'httpclient'
|
|
3
3
|
require 'tankard/error'
|
4
4
|
|
5
5
|
module Tankard
|
6
|
+
# Handles making actual requests and checking them for any invalid status codes
|
7
|
+
#
|
8
|
+
# @author Matthew Shafer
|
6
9
|
class Request
|
7
10
|
|
8
11
|
def initialize(api_key)
|
@@ -10,36 +13,34 @@ module Tankard
|
|
10
13
|
@api_key = api_key
|
11
14
|
end
|
12
15
|
|
13
|
-
def get(route, params={})
|
16
|
+
def get(route, params = {})
|
14
17
|
params[:key] = @api_key
|
15
18
|
request = @http.get(build_request_url(route), params)
|
16
19
|
raise_if_status_not_ok(request.status)
|
17
20
|
load_json(request.body)
|
18
21
|
end
|
19
22
|
|
20
|
-
|
23
|
+
private
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
25
|
+
def raise_if_status_not_ok(status)
|
26
|
+
case status
|
27
|
+
when 200
|
28
|
+
true
|
29
|
+
when 401
|
30
|
+
fail Tankard::Error::ApiKeyUnauthorized
|
31
|
+
else
|
32
|
+
fail Tankard::Error::HttpError
|
31
33
|
end
|
34
|
+
end
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
def build_request_url(route)
|
37
|
+
Tankard::Configuration::BREWERYDB_URL + route
|
38
|
+
end
|
36
39
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
40
|
+
def load_json(json_data)
|
41
|
+
MultiJson.load(json_data)
|
42
|
+
rescue MultiJson::LoadError
|
43
|
+
raise Tankard::Error::LoadError
|
44
|
+
end
|
44
45
|
end
|
45
|
-
end
|
46
|
+
end
|
data/lib/tankard/version.rb
CHANGED
@@ -1,30 +1,30 @@
|
|
1
|
-
shared_examples
|
1
|
+
shared_examples 'the find method' do
|
2
2
|
|
3
|
-
|
3
|
+
context 'when looking up a valid item' do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
it 'returns data on the item' do
|
6
|
+
expect(context.find(valid_items.first)).to eql(valid_responses.first)
|
7
|
+
end
|
8
|
+
end
|
9
9
|
|
10
|
-
|
10
|
+
context 'when looking up an invalid item' do
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
it 'returns nil when not found' do
|
13
|
+
expect(context.find(invalid_items.first)).to eql(nil)
|
14
|
+
end
|
15
|
+
end
|
16
16
|
|
17
|
-
|
17
|
+
context 'when looking up multiple valid items' do
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
it 'returns an array of data with each item' do
|
20
|
+
expect(context.find(valid_items)).to eql(valid_responses)
|
21
|
+
end
|
22
|
+
end
|
23
23
|
|
24
|
-
|
24
|
+
context 'when looking up multiple items and one is invalid' do
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
26
|
+
it 'returns an array with only the valid items' do
|
27
|
+
expect(context.find(valid_invalid_items)).to eql(valid_responses)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|