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
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MjQzMTM3ZWNlM2JhODRkM2FkMDU2MDAzOWVkNzUwOGFkOWU1OTY5OA==
5
+ data.tar.gz: !binary |-
6
+ ZGM5NmZmMmE1MDcyYWUyMjFkODZkMmFlYjNiNjI5NTM0Y2JkMGUyZA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ OGIxYmNhNjNlMWZiNGZhYzE0MzdjYjM4MzQ5YmYzMTUwNDRiOWM2YzczNDdl
10
+ ZDRkZjQzNmNjOThjNGY5YzkzZmNmMzRjYzViMTAzZWJiNWY1Yzk3ZDA2M2Ey
11
+ OTQwNjkyNTkzMjE0YTY3MzE1ZjA3OWZhYjRiYjlmMDg3NGQzZDY=
12
+ data.tar.gz: !binary |-
13
+ NjBiYjUxZGRmNTdmMjEyYTNjY2U0ZmMzYjQ5YTUxNjEyMThiNDAwNTBhMjY4
14
+ YjQzOGJhZWJlMmM4YWY4NzdiZDE4ZmI5ZGMxMWJlM2ZmZjY4OTAzMWFmMTdj
15
+ MzI2NGY4ZTNjYTYwMDcyZGJjYTljYmQ3NGU2NTA2MTNhMzJiYjg=
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  *.swp
4
4
  .bundle
5
5
  .config
6
+ .rbenv-version
6
7
  .rvmrc
7
8
  .yardoc
8
9
  Gemfile.lock
@@ -15,6 +16,7 @@ lib/bundler/man
15
16
  pkg
16
17
  rdoc
17
18
  spec/reports
19
+ tags
18
20
  test/tmp
19
21
  test/version_tmp
20
22
  tmp
data/.rspec CHANGED
@@ -1,2 +1,4 @@
1
1
  --color
2
2
  --format progress
3
+
4
+ -r pry
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ script: bundle exec rspec
3
+ rvm:
4
+ - 1.9.2
5
+ - 1.9.3
data/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ ## BreweryDB 0.0.2 (Unreleased)
4
+
5
+ * Raise exceptions on unsuccessful responses
6
+ * Return the data directly on successful responses ([Steven Harman][stevenharman])
7
+ * Add support for `brewery/:id/beers` endpoint ([Steven Harman][stevenharman])
8
+ * Require `faraday_middleare` ~> 0.8 ([Steven Harman][stevenharman])
9
+ * Add support for handling webhook parameters ([Steven Harman][stevenharman])
10
+
11
+ ## BreweryDB 0.0.1
12
+
13
+ * Initial release
14
+
15
+ [stevenharman]: http://github.com/stevenharman
data/README.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # BreweryDB
2
2
 
3
- A Ruby library for interfacing with the [BreweryDB][] API.
3
+ [![Build Status][travis]][travis-web]
4
+
5
+ [travis]: https://secure.travis-ci.org/tylerhunt/brewery_db.png
6
+ [travis-web]: http://travis-ci.org/tylerhunt/brewery_db
7
+
8
+ A Ruby library for using the [BreweryDB][] API.
4
9
 
5
10
  [brewerydb]: http://www.brewerydb.com/
6
11
 
@@ -29,55 +34,94 @@ one, you may [request one here][api-key].
29
34
 
30
35
  [api-key]: http://www.brewerydb.com/developers
31
36
 
32
- Use the following method to configure your API key:
37
+ You can use the following method to configure your API key:
33
38
 
34
39
  ``` ruby
35
- BreweryDB.configure do |config|
40
+ brewery_db = BreweryDB::Client.new do |config|
36
41
  config.api_key = API_KEY
37
42
  end
38
43
  ```
39
44
 
40
- If you'd like to use multiple instance of the API with different keys, you may
41
- instantiate the `BreweryDB::Client` directly and treat those instances the same
42
- as the `BreweryDB` module:
45
+
46
+ ## Usage
47
+
48
+ Once an API key has been set, resources can be called on the client instance.
43
49
 
44
50
  ``` ruby
45
- brewery_db = BreweryDB::Client.new
51
+ brewery_db.beers.all(abv: '5.5')
52
+ brewery_db.beers.find('vYlBZQ')
46
53
 
47
- brewery_db.configure do |config|
48
- config.api_key = API_KEY
49
- end
54
+ brewery_db.breweries.all(established: 2006)
55
+ brewery_db.breweries.find('d1zSa7')
56
+
57
+ brewery_db.brewery('d1zSa7').beers
58
+
59
+ brewery_db.categories.all
60
+ brewery_db.categories.find(1)
61
+
62
+ brewery_db.glassware.all
63
+ brewery_db.glassware.find(1)
64
+
65
+ brewery_db.search.all(q: 'IPA')
66
+ brewery_db.search.beers(q: 'IPA')
67
+ brewery_db.search.breweries(q: 'IPA')
68
+ brewery_db.search.guilds(q: 'IPA')
69
+ brewery_db.search.events(q: 'IPA')
70
+
71
+ brewery_db.styles.all
72
+ brewery_db.styles.find(1)
50
73
  ```
51
74
 
75
+ ### WebHooks
52
76
 
53
- ## Usage
77
+ The BreweryDB API also provides [WebHooks][webhooks] which can be use to:
54
78
 
55
- Once the API key has been configured, resources may be called off the module
56
- directly or off your client instances:
79
+ > keep your local data stores in sync with the main BreweryDB API. Instead of
80
+ > having to constantly query the API, webhooks will send you a message when
81
+ > something changes.
57
82
 
58
- ``` ruby
59
- BreweryDB.beers.all(abv: '5.5')
60
- BreweryDB.beers.find('vYlBZQ')
83
+ This library provides a simple abstraction over the data posted by those
84
+ webhooks.
85
+
86
+ ```ruby
87
+ webhook = BreweryDB::WebHook.new(webhook_params_hash)
88
+ ```
89
+
90
+ #### Validating a WebHook
91
+
92
+ The `webhook_params_hash` should contain the `key`, `nonce`, `action`, etc.
93
+ sent as the payload of the webhook. A `BreweryDB::WebHook` object can validate
94
+ the posted data by SHA1 hashing your API key with the `nonce` value and
95
+ comparing it to the `key` value (as per the [docs][webhooks]).
96
+
97
+ ```ruby
98
+ webhook.valid?(API_KEY) #=> true or false
99
+ ```
61
100
 
62
- BreweryDB.breweries.all(established: 2006)
63
- BreweryDB.breweries.find('d1zSa7')
101
+ #### Idiomatic wrapper over WebHook parameters
64
102
 
65
- BreweryDB.categories.all
66
- BreweryDB.categories.find(1)
103
+ The `BreweryDB::WebHook` object also provides an idiomatic Ruby wrapper over
104
+ the parameters. For example, one of the parameters posted in a webhook is
105
+ `attributeId`, which is the BreweryDB id for a brewery, beer, etc. This
106
+ parameter is exposed by an instance of `BreweryDB::WebHook` via
67
107
 
68
- BreweryDB.glassware.all
69
- BreweryDB.glassware.find(1)
108
+ ```ruby
109
+ webhook.attribute_id #=> 'x6bRxw'
110
+ ```
70
111
 
71
- BreweryDB.search.all(q: 'IPA')
72
- BreweryDB.search.beers(q: 'IPA')
73
- BreweryDB.search.breweries(q: 'IPA')
74
- BreweryDB.search.guilds(q: 'IPA')
75
- BreweryDB.search.events(q: 'IPA')
112
+ The full list of parameters available are:
76
113
 
77
- BreweryDB.styles.all
78
- BreweryDB.styles.find(1)
114
+ ```ruby
115
+ webhook.action #=> 'insert'
116
+ webhook.attribute #=> 'beer'
117
+ webhook.attribute_id #=> 'x6bRxw'
118
+ webhook.key #=> 'some-long-key-value-here'
119
+ webhook.nonce #=> 'some-long-nonce-value-here'
120
+ webhook.sub_action #=> 'none'
121
+ webhook.timestamp #=> '1350573527'
79
122
  ```
80
123
 
124
+ [webhooks]: http://developer.pintlabs.com/brewerydb/webhooks/
81
125
 
82
126
  ## Contributing
83
127
 
@@ -88,6 +132,14 @@ BreweryDB.styles.find(1)
88
132
  5. Create a new Pull Request.
89
133
 
90
134
 
135
+ ## Contributors
136
+
137
+ Thanks to the following people who have contributed patches or helpful
138
+ suggestions:
139
+
140
+ * [Steven Harman](https://github.com/stevenharman)
141
+
142
+
91
143
  ## Copyright
92
144
 
93
145
  Copyright © 2012 Tyler Hunt. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,3 +1,8 @@
1
1
  #!/usr/bin/env rake
2
2
 
3
3
  require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/brewery_db.gemspec CHANGED
@@ -3,16 +3,17 @@ require './lib/brewery_db/version'
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = 'brewery_db'
5
5
  gem.version = BreweryDB::VERSION
6
- gem.summary = 'A Ruby library for interfacing with the BreweryDB API.'
6
+ gem.summary = 'A Ruby library for using the BreweryDB API.'
7
7
  gem.homepage = 'http://github.com/tylerhunt/brewery_db'
8
- gem.author = 'Tyler Hunt'
8
+ gem.authors = ['Tyler Hunt', 'Steven Harman']
9
9
 
10
10
  gem.required_ruby_version = '>= 1.9'
11
11
 
12
12
  gem.add_dependency 'faraday', '~> 0.8.0'
13
- gem.add_dependency 'faraday_middleware'
14
- gem.add_dependency 'hashie', '~> 1.1'
15
- gem.add_development_dependency 'rspec', '~> 2.0'
13
+ gem.add_dependency 'faraday_middleware', '~> 0.8'
14
+ gem.add_dependency 'hashie', '>= 1.1', '< 3'
15
+ gem.add_development_dependency 'pry'
16
+ gem.add_development_dependency 'rspec', '~> 2.11'
16
17
  gem.add_development_dependency 'vcr', '~> 2.0'
17
18
 
18
19
  gem.files = `git ls-files`.split($\)
data/lib/brewery_db.rb CHANGED
@@ -1,36 +1,32 @@
1
1
  require 'brewery_db/version'
2
2
 
3
3
  module BreweryDB
4
+ Error = Class.new(StandardError)
5
+ BadRequest = Class.new(Error)
6
+ NotFound = Class.new(Error)
7
+ RateLimitExceeded = Class.new(Error)
8
+ Unauthorized = Class.new(Error)
9
+
4
10
  autoload :Client, 'brewery_db/client'
11
+ autoload :Collection, 'brewery_db/collection'
5
12
  autoload :Config, 'brewery_db/config'
13
+ autoload :Mash, 'brewery_db/mash'
14
+ autoload :Request, 'brewery_db/request'
6
15
  autoload :Resource, 'brewery_db/resource'
7
16
  autoload :Response, 'brewery_db/response'
17
+ autoload :WebHook, 'brewery_db/web_hook'
18
+
19
+ module Middleware
20
+ autoload :ErrorHandler, 'brewery_db/middleware/error_handler'
21
+ end
8
22
 
9
23
  module Resources
10
24
  autoload :Beers, 'brewery_db/resources/beers'
11
25
  autoload :Breweries, 'brewery_db/resources/breweries'
26
+ autoload :Brewery, 'brewery_db/resources/brewery'
12
27
  autoload :Categories, 'brewery_db/resources/categories'
13
28
  autoload :Glassware, 'brewery_db/resources/glassware'
14
29
  autoload :Search, 'brewery_db/resources/search'
15
30
  autoload :Styles, 'brewery_db/resources/styles'
16
31
  end
17
-
18
- extend self
19
-
20
- def respond_to?(method, include_private=false)
21
- super || client.respond_to?(method, include_private)
22
- end
23
-
24
- def method_missing(method, *args, &block)
25
- if client.respond_to?(method)
26
- client.send(method, *args, &block)
27
- else
28
- super
29
- end
30
- end
31
-
32
- def client
33
- @client ||= Client.new
34
- end
35
- private :client
36
32
  end
@@ -1,36 +1,48 @@
1
1
  module BreweryDB
2
2
  class Client
3
+ def initialize(&block)
4
+ configure(&block) if block_given?
5
+ end
6
+
3
7
  def config
4
8
  @config ||= Config.new
5
9
  end
6
10
 
7
11
  def configure
8
12
  yield(config)
9
- config
13
+ self
10
14
  end
11
15
 
12
16
  def beers
13
- @beers ||= Resources::Beers.new(self)
17
+ @beers ||= Resources::Beers.new(config)
18
+ end
19
+
20
+ # Builds a new instance of the brewery resource.
21
+ #
22
+ # @param id [String] the brewery ID
23
+ # @return <Resources::Breweries> an instance of the brewery resource
24
+ def brewery(id)
25
+ Resources::Brewery.new(config, id: id)
14
26
  end
15
27
 
16
28
  def breweries
17
- @breweries ||= Resources::Breweries.new(self)
29
+ @breweries ||= Resources::Breweries.new(config)
18
30
  end
19
31
 
20
32
  def categories
21
- @categories ||= Resources::Categories.new(self)
33
+ @categories ||= Resources::Categories.new(config)
22
34
  end
23
35
 
24
36
  def glassware
25
- @glassware ||= Resources::Glassware.new(self)
37
+ @glassware ||= Resources::Glassware.new(config)
26
38
  end
27
39
 
28
40
  def search
29
- @search ||= Resources::Search.new(self)
41
+ @search ||= Resources::Search.new(config)
30
42
  end
31
43
 
32
44
  def styles
33
- @styles ||= Resources::Styles.new(self)
45
+ @styles ||= Resources::Styles.new(config)
34
46
  end
35
47
  end
36
48
  end
@@ -0,0 +1,42 @@
1
+ module BreweryDB
2
+ class Collection
3
+ include Enumerable
4
+
5
+ BATCH_SIZE = 50
6
+
7
+ attr_reader :size
8
+ alias length size
9
+
10
+ def initialize(response)
11
+ self.response = response
12
+ end
13
+
14
+ def count(*args, &block)
15
+ # The Ruby documentation is wrong, and Enumerable#count no longer calls
16
+ # #size, so let's make sure it's used here when no arguments are given.
17
+ if args.empty? && !block_given?
18
+ size
19
+ else
20
+ super
21
+ end
22
+ end
23
+
24
+ def each
25
+ return to_enum unless block_given?
26
+
27
+ while @collection.any?
28
+ @collection.each { |element| yield(element) }
29
+ break if @collection.size < BATCH_SIZE
30
+ self.response = @response.next_page
31
+ end
32
+ end
33
+
34
+ def response=(response)
35
+ @response = response
36
+ @collection = Array(response.data) || []
37
+ @size = response.count || 0
38
+ @page_count = response.page_count
39
+ end
40
+ private :response=
41
+ end
42
+ end
@@ -2,19 +2,20 @@ require 'faraday'
2
2
 
3
3
  module BreweryDB
4
4
  class Config
5
- ADAPTER = Faraday.default_adapter
6
- ENDPOINT = 'http://api.brewerydb.com/v2'
7
- MIDDLEWARE = []
5
+ BASE_URI = 'http://api.brewerydb.com/v2'
8
6
  USER_AGENT = "BreweryDB Ruby Gem #{BreweryDB::VERSION}"
7
+ TIMEOUT = 60
9
8
 
10
9
  attr_accessor :adapter
11
10
  attr_accessor :api_key
12
- attr_accessor :endpoint
11
+ attr_accessor :base_uri
12
+ attr_accessor :timeout
13
13
  attr_accessor :user_agent
14
14
 
15
15
  def initialize
16
- self.adapter = ADAPTER
17
- self.endpoint = ENDPOINT
16
+ self.adapter = Faraday.default_adapter
17
+ self.base_uri = BASE_URI
18
+ self.timeout = TIMEOUT
18
19
  self.user_agent = USER_AGENT
19
20
  end
20
21
  end
@@ -0,0 +1,18 @@
1
+ require 'hashie'
2
+
3
+ module BreweryDB
4
+ class Mash < 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
10
+ end
11
+ protected :convert_key
12
+
13
+ def convert_value(value, duping=false)
14
+ value.is_a?(String) ? super.gsub("\r\n", "\n") : super
15
+ end
16
+ protected :convert_value
17
+ end
18
+ end