brewery_db 0.0.1 → 0.1.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.
Files changed (65) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +2 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/CHANGELOG.md +15 -0
  6. data/README.md +81 -29
  7. data/Rakefile +5 -0
  8. data/brewery_db.gemspec +6 -5
  9. data/lib/brewery_db.rb +15 -19
  10. data/lib/brewery_db/client.rb +19 -7
  11. data/lib/brewery_db/collection.rb +42 -0
  12. data/lib/brewery_db/config.rb +7 -6
  13. data/lib/brewery_db/mash.rb +18 -0
  14. data/lib/brewery_db/middleware/error_handler.rb +28 -0
  15. data/lib/brewery_db/request.rb +27 -0
  16. data/lib/brewery_db/resource.rb +16 -22
  17. data/lib/brewery_db/resources/beers.rb +2 -2
  18. data/lib/brewery_db/resources/breweries.rb +2 -2
  19. data/lib/brewery_db/resources/brewery.rb +16 -0
  20. data/lib/brewery_db/resources/categories.rb +2 -2
  21. data/lib/brewery_db/resources/glassware.rb +2 -2
  22. data/lib/brewery_db/resources/search.rb +1 -1
  23. data/lib/brewery_db/resources/styles.rb +2 -2
  24. data/lib/brewery_db/response.rb +26 -12
  25. data/lib/brewery_db/version.rb +1 -1
  26. data/lib/brewery_db/web_hook.rb +32 -0
  27. data/spec/brewery_db/client_spec.rb +41 -30
  28. data/spec/brewery_db/config_spec.rb +25 -28
  29. data/spec/brewery_db/{response_spec.rb → mash_spec.rb} +1 -1
  30. data/spec/brewery_db/middleware/error_handler_spec.rb +49 -0
  31. data/spec/brewery_db/resource_spec.rb +35 -22
  32. data/spec/brewery_db/resources/beers_spec.rb +10 -82
  33. data/spec/brewery_db/resources/breweries_spec.rb +10 -54
  34. data/spec/brewery_db/resources/brewery_spec.rb +27 -0
  35. data/spec/brewery_db/resources/categories_spec.rb +10 -38
  36. data/spec/brewery_db/resources/glassware_spec.rb +10 -36
  37. data/spec/brewery_db/resources/search_spec.rb +19 -61
  38. data/spec/brewery_db/resources/styles_spec.rb +10 -72
  39. data/spec/brewery_db/web_hook_spec.rb +79 -0
  40. data/spec/fixtures/BreweryDB_Resource/_get/a_list_of_resources/can_be_enumerated.yml +515 -0
  41. data/spec/fixtures/BreweryDB_Resource/_get/a_not_found_request/raises_an_exception.yml +38 -0
  42. data/spec/fixtures/BreweryDB_Resource/_get/a_not_found_request/sets_the_exception_message_to_the_error_message_in_the_response.yml +38 -0
  43. data/spec/fixtures/BreweryDB_Resource/_get/an_OK_request/name/.yml +54 -0
  44. data/spec/fixtures/BreweryDB_Resources_Beers/_all/fetches_all_of_the_beers_at_once.yml +889 -0
  45. data/spec/fixtures/BreweryDB_Resources_Beers/_find/fetches_only_the_beer_asked_for.yml +61 -0
  46. data/spec/fixtures/BreweryDB_Resources_Breweries/_all/fetches_all_of_the_breweries_at_once.yml +430 -0
  47. data/spec/fixtures/BreweryDB_Resources_Breweries/_find/fetches_only_the_brewery_asked_for.yml +57 -0
  48. data/spec/fixtures/BreweryDB_Resources_Categories/_all/fetches_all_of_the_cagtegories_at_once.yml +49 -0
  49. data/spec/fixtures/BreweryDB_Resources_Categories/_find/fetches_only_the_category_asked_for.yml +39 -0
  50. data/spec/fixtures/BreweryDB_Resources_Glassware/_all/fetches_all_of_the_glassware_at_once.yml +45 -0
  51. data/spec/fixtures/BreweryDB_Resources_Glassware/_find/fetches_only_the_glassware_asked_for.yml +39 -0
  52. data/spec/fixtures/BreweryDB_Resources_Search/_all/fetches_all_of_the_search_results_at_once.yml +1132 -0
  53. data/spec/fixtures/BreweryDB_Resources_Styles/_all/fetches_all_of_the_styles_at_once.yml +1866 -0
  54. data/spec/fixtures/BreweryDB_Resources_Styles/_find/fetches_only_the_style_asked_for.yml +50 -0
  55. data/spec/spec_helper.rb +4 -4
  56. data/spec/support/shared/a_resource.rb +3 -9
  57. data/spec/support/vcr.rb +6 -1
  58. metadata +82 -42
  59. data/spec/brewery_db_spec.rb +0 -18
  60. data/spec/fixtures/beers.yml +0 -445
  61. data/spec/fixtures/breweries.yml +0 -409
  62. data/spec/fixtures/categories.yml +0 -102
  63. data/spec/fixtures/glassware.yml +0 -65
  64. data/spec/fixtures/search.yml +0 -314
  65. data/spec/fixtures/styles.yml +0 -317
@@ -0,0 +1,28 @@
1
+ module BreweryDB
2
+ module Middleware
3
+ class ErrorHandler < Faraday::Response::Middleware
4
+ def on_complete(env)
5
+ case env[:status]
6
+ when 200
7
+ when 400 then fail with(BadRequest, env)
8
+ when 401 then fail with(rate_limit_exceeded_or_unauthorized(env[:response_headers]), env)
9
+ when 404 then fail with(NotFound, env)
10
+ else fail with(Error, env)
11
+ end
12
+ end
13
+
14
+ def rate_limit_exceeded_or_unauthorized(headers)
15
+ rate_limit = headers.fetch('x-ratelimit-remaining') { :rate_limit_unknown }
16
+
17
+ rate_limit == '0' ? RateLimitExceeded : Unauthorized
18
+ end
19
+ private :rate_limit_exceeded_or_unauthorized
20
+
21
+ def with(error_class, env)
22
+ message = "Status => #{env[:status]}. Error message => #{env[:body].error_message}"
23
+ error_class.new(message)
24
+ end
25
+ private :with
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ module BreweryDB
2
+ class Request
3
+ def initialize(connection, path, params={})
4
+ @connection = connection
5
+ @path = path
6
+ @params = params
7
+ end
8
+
9
+ def response
10
+ Response.new(response_body, self)
11
+ end
12
+
13
+ def next_page
14
+ self.class.new(@connection, @path, @params.merge(p: page_number + 1))
15
+ end
16
+
17
+ def response_body
18
+ @connection.get(@path, @params).body
19
+ end
20
+ private :response_body
21
+
22
+ def page_number
23
+ @params[:p] || 1
24
+ end
25
+ private :page_number
26
+ end
27
+ end
@@ -3,34 +3,28 @@ require 'faraday_middleware'
3
3
 
4
4
  module BreweryDB
5
5
  class Resource
6
- def initialize(client)
7
- @client = client
8
- end
9
-
10
- # TODO: Make this private once the appropriate test coverage is in place.
11
- def connection
12
- # TODO: Use an instance-level option once faraday_middleware is updated.
13
- FaradayMiddleware::Mashify.mash_class = Response
14
-
15
- Faraday.new(
16
- url: @client.config.endpoint,
17
- headers: { user_agent: @client.config.user_agent }
18
- ) do |connection|
19
- connection.response(:mashify)
20
- connection.response(:json, content_type: /\bjson$/)
21
-
22
- connection.adapter(@client.config.adapter)
23
- end
6
+ def initialize(config)
7
+ @config = config
24
8
  end
25
9
 
26
10
  def get(path, params={})
27
- connection.get(path, default_params.merge(params)).body
11
+ Request.new(connection, path, params).response
28
12
  end
29
13
  private :get
30
14
 
31
- def default_params
32
- { key: @client.config.api_key }
15
+ def connection
16
+ Faraday.new(request: { timeout: @config.timeout }) do |builder|
17
+ builder.url_prefix = @config.base_uri
18
+ builder.headers[:user_agent] = @config.user_agent
19
+ builder.params[:key] = @config.api_key
20
+
21
+ builder.use(Middleware::ErrorHandler)
22
+ builder.response(:mashify, mash_class: Mash)
23
+ builder.response(:json, content_type: /\bjson$/)
24
+
25
+ builder.adapter(@config.adapter)
26
+ end
33
27
  end
34
- private :default_params
28
+ private :connection
35
29
  end
36
30
  end
@@ -2,11 +2,11 @@ module BreweryDB
2
2
  module Resources
3
3
  class Beers < Resource
4
4
  def all(params={})
5
- get('beers', params)
5
+ get('beers', params).collection
6
6
  end
7
7
 
8
8
  def find(id, params={})
9
- get('beer/%s' % id, params)
9
+ get('beer/%s' % id, params).data
10
10
  end
11
11
  end
12
12
  end
@@ -2,11 +2,11 @@ module BreweryDB
2
2
  module Resources
3
3
  class Breweries < Resource
4
4
  def all(params={})
5
- get('breweries', params)
5
+ get('breweries', params).collection
6
6
  end
7
7
 
8
8
  def find(id, params={})
9
- get('brewery/%s' % id, params)
9
+ get('brewery/%s' % id, params).data
10
10
  end
11
11
  end
12
12
  end
@@ -0,0 +1,16 @@
1
+ module BreweryDB
2
+ module Resources
3
+ class Brewery < Resource
4
+ attr_reader :id
5
+
6
+ def initialize(config, options={})
7
+ @id = options[:id]
8
+ super(config)
9
+ end
10
+
11
+ def beers(params={})
12
+ get("brewery/#{id}/beers", params).data
13
+ end
14
+ end
15
+ end
16
+ end
@@ -2,11 +2,11 @@ module BreweryDB
2
2
  module Resources
3
3
  class Categories < Resource
4
4
  def all(params={})
5
- get('categories', params)
5
+ get('categories', params).data
6
6
  end
7
7
 
8
8
  def find(id, params={})
9
- get('category/%s' % id, params)
9
+ get('category/%s' % id, params).data
10
10
  end
11
11
  end
12
12
  end
@@ -2,11 +2,11 @@ module BreweryDB
2
2
  module Resources
3
3
  class Glassware < Resource
4
4
  def all(params={})
5
- get('glassware', params)
5
+ get('glassware', params).data
6
6
  end
7
7
 
8
8
  def find(id, params={})
9
- get('glass/%s' % id, params)
9
+ get('glass/%s' % id, params).data
10
10
  end
11
11
  end
12
12
  end
@@ -2,7 +2,7 @@ module BreweryDB
2
2
  module Resources
3
3
  class Search < Resource
4
4
  def all(params={})
5
- get('search', params)
5
+ get('search', params).collection
6
6
  end
7
7
 
8
8
  def beers(params={})
@@ -2,11 +2,11 @@ module BreweryDB
2
2
  module Resources
3
3
  class Styles < Resource
4
4
  def all(params={})
5
- get('styles', params)
5
+ get('styles', params).data
6
6
  end
7
7
 
8
8
  def find(id, params={})
9
- get('style/%s' % id, params)
9
+ get('style/%s' % id, params).data
10
10
  end
11
11
  end
12
12
  end
@@ -1,18 +1,32 @@
1
- require 'hashie'
2
-
3
1
  module BreweryDB
4
- class Response < Hashie::Mash
5
- def convert_key(key)
6
- key = key.to_s.dup
7
- key.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
8
- key.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
9
- key.tr('-', '_').downcase
2
+ class Response
3
+ def initialize(body, request)
4
+ @body = body
5
+ @request = request
6
+ end
7
+
8
+ def data
9
+ @body.data
10
+ end
11
+
12
+ def collection
13
+ Collection.new(self)
14
+ end
15
+
16
+ def next_page
17
+ @request.next_page.response
18
+ end
19
+
20
+ def page_number
21
+ @body.current_page
22
+ end
23
+
24
+ def page_count
25
+ @body.number_of_pages
10
26
  end
11
- protected :convert_key
12
27
 
13
- def convert_value(value, duping=false)
14
- value.is_a?(String) ? super.gsub("\r\n", "\n") : super
28
+ def count
29
+ @body.total_results
15
30
  end
16
- protected :convert_value
17
31
  end
18
32
  end
@@ -1,3 +1,3 @@
1
1
  module BreweryDB
2
- VERSION = '0.0.1'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -0,0 +1,32 @@
1
+ require 'digest/sha1'
2
+
3
+ module BreweryDB
4
+ class WebHook
5
+ attr_reader :action
6
+ attr_reader :attribute
7
+ attr_reader :attribute_id
8
+ attr_reader :key
9
+ attr_reader :nonce
10
+ attr_reader :sub_action
11
+ attr_reader :timestamp
12
+
13
+ def initialize(args)
14
+ @action = args[:action]
15
+ @attribute = args[:attribute]
16
+ @attribute_id = args[:attributeId]
17
+ @key = args[:key]
18
+ @nonce = args[:nonce]
19
+ @sub_action = args[:subAction]
20
+ @timestamp = args[:timestamp]
21
+ end
22
+
23
+ def valid?(api_key)
24
+ hash(api_key) == key
25
+ end
26
+
27
+ def hash(api_key)
28
+ Digest::SHA1.hexdigest("#{api_key}#{nonce}")
29
+ end
30
+ private :hash
31
+ end
32
+ end
@@ -2,43 +2,54 @@ require 'spec_helper'
2
2
 
3
3
  describe BreweryDB::Client do
4
4
  context '#config' do
5
- subject { described_class.new.config }
6
-
7
- it { should be_a(BreweryDB::Config) }
5
+ it 'returns a configuration instance' do
6
+ subject.config.should be_a(BreweryDB::Config)
7
+ end
8
8
 
9
- its(:adapter) { should == BreweryDB::Config::ADAPTER }
10
- its(:api_key) { should == nil }
11
- its(:endpoint) { should == BreweryDB::Config::ENDPOINT }
9
+ it 'memoizes the return value' do
10
+ BreweryDB::Config.should_receive(:new).once.and_return(stub)
11
+ 2.times { subject.config }
12
+ end
12
13
  end
13
14
 
14
15
  context '#configure' do
15
- subject do
16
- described_class.new.configure do |config|
17
- config.adapter = :typhoeus
18
- config.api_key = 'A1029384756B'
19
- config.endpoint = 'http://api.playground.brewerydb.com'
20
- end
16
+ it 'can set the adapter' do
17
+ expect {
18
+ subject.configure { |config| config.adapter = :typhoeus }
19
+ }.to change(subject.config, :adapter).to(:typhoeus)
21
20
  end
22
21
 
23
- its(:adapter) { should == :typhoeus }
24
- its(:api_key) { should == 'A1029384756B' }
25
- its(:endpoint) { should == 'http://api.playground.brewerydb.com' }
26
- end
22
+ it 'can set the API key' do
23
+ expect {
24
+ subject.configure { |config| config.api_key = 'secret' }
25
+ }.to change(subject.config, :api_key).to('secret')
26
+ end
27
27
 
28
- {
29
- beers: BreweryDB::Resources::Beers,
30
- breweries: BreweryDB::Resources::Breweries,
31
- categories: BreweryDB::Resources::Categories,
32
- glassware: BreweryDB::Resources::Glassware,
33
- search: BreweryDB::Resources::Search,
34
- styles: BreweryDB::Resources::Styles
35
- }.each do |method, resource|
36
- context "##{method}" do
37
- specify do
38
- endpoint = resource.new(subject)
39
- resource.should_receive(:new).and_return(endpoint)
40
- subject.send(method).should == endpoint
41
- end
28
+ it 'can set the base URI' do
29
+ expect {
30
+ subject.configure { |config| config.base_uri = 'http://example.com' }
31
+ }.to change(subject.config, :base_uri).to('http://example.com')
32
+ end
33
+
34
+ it 'can set the timeout' do
35
+ expect {
36
+ subject.configure { |config| config.timeout = 42 }
37
+ }.to change(subject.config, :timeout).to(42)
38
+ end
39
+
40
+ it 'can set the user agent' do
41
+ expect {
42
+ subject.configure { |config| config.user_agent = 'Brewdega' }
43
+ }.to change(subject.config, :user_agent).to('Brewdega')
42
44
  end
43
45
  end
46
+
47
+ its(:beers) { should be_a(BreweryDB::Resources::Beers) }
48
+ its(:breweries) { should be_a(BreweryDB::Resources::Breweries) }
49
+ its(:categories) { should be_a(BreweryDB::Resources::Categories) }
50
+ its(:glassware) { should be_a(BreweryDB::Resources::Glassware) }
51
+ its(:search) { should be_a(BreweryDB::Resources::Search) }
52
+ its(:styles) { should be_a(BreweryDB::Resources::Styles) }
53
+
54
+ it { subject.brewery('KlSsWY').should be_a(BreweryDB::Resources::Brewery) }
44
55
  end
@@ -1,27 +1,16 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe BreweryDB::Config do
4
- {
5
- ADAPTER: Faraday.default_adapter,
6
- ENDPOINT: 'http://api.brewerydb.com/v2',
7
- USER_AGENT: "BreweryDB Ruby Gem #{BreweryDB::VERSION}"
8
- }.each do |constant, value|
9
- context constant do
10
- subject { described_class.const_get(constant) }
11
-
12
- it { should == value }
13
- end
14
- end
15
-
16
4
  context 'defaults' do
17
- its(:adapter) { should == described_class::ADAPTER }
18
- its(:api_key) { should == nil }
19
- its(:endpoint) { should == described_class::ENDPOINT }
20
- its(:user_agent) { should == described_class::USER_AGENT }
5
+ its(:adapter) { should eq Faraday.default_adapter }
6
+ its(:api_key) { should be_nil }
7
+ its(:base_uri) { should eq described_class::BASE_URI }
8
+ its(:timeout) { should eq described_class::TIMEOUT }
9
+ its(:user_agent) { should eq described_class::USER_AGENT }
21
10
  end
22
11
 
23
12
  context '#adapter=' do
24
- specify do
13
+ it do
25
14
  expect {
26
15
  subject.adapter = :typhoeus
27
16
  }.to change(subject, :adapter).to(:typhoeus)
@@ -29,26 +18,34 @@ describe BreweryDB::Config do
29
18
  end
30
19
 
31
20
  context '#api_key=' do
32
- specify do
21
+ it do
22
+ expect {
23
+ subject.api_key = 'secret'
24
+ }.to change(subject, :api_key).to('secret')
25
+ end
26
+ end
27
+
28
+ context '#base_uri=' do
29
+ it do
33
30
  expect {
34
- subject.api_key = 'A1029384756B'
35
- }.to change(subject, :api_key).to('A1029384756B')
31
+ subject.base_uri = 'http://example.com'
32
+ }.to change(subject, :base_uri).to('http://example.com')
36
33
  end
37
34
  end
38
35
 
39
- context '#endpoint=' do
40
- specify do
36
+ context 'timeout=' do
37
+ it do
41
38
  expect {
42
- subject.endpoint = 'http://api.playground.brewerydb.com'
43
- }.to change(subject, :endpoint).to('http://api.playground.brewerydb.com')
39
+ subject.timeout = 42
40
+ }.to change(subject, :timeout).to(42)
44
41
  end
45
42
  end
46
43
 
47
- context '#user_agent=' do
48
- specify do
44
+ context 'user_agent=' do
45
+ it do
49
46
  expect {
50
- subject.user_agent = 'A BreweryDB Application'
51
- }.to change(subject, :user_agent).to('A BreweryDB Application')
47
+ subject.user_agent = 'Brewdega'
48
+ }.to change(subject, :user_agent).to('Brewdega')
52
49
  end
53
50
  end
54
51
  end