yelp 1.0.0 → 2.0.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 (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE.txt +22 -504
  5. data/README.md +152 -0
  6. data/Rakefile +4 -24
  7. data/lib/yelp.rb +18 -13
  8. data/lib/yelp/burst_struct.rb +51 -0
  9. data/lib/yelp/client.rb +86 -86
  10. data/lib/yelp/configuration.rb +31 -0
  11. data/lib/yelp/endpoint/business.rb +42 -0
  12. data/lib/yelp/endpoint/search.rb +170 -0
  13. data/lib/yelp/error.rb +55 -0
  14. data/lib/yelp/version.rb +3 -0
  15. data/spec/fixtures/vcr_cassettes/business.yml +73 -0
  16. data/spec/fixtures/vcr_cassettes/search.yml +361 -0
  17. data/spec/fixtures/vcr_cassettes/search_bounding_box.yml +359 -0
  18. data/spec/fixtures/vcr_cassettes/search_by_coordinates.yml +387 -0
  19. data/spec/spec_helper.rb +14 -0
  20. data/spec/support/request_error.rb +11 -0
  21. data/spec/support/shared_configuration.rb +11 -0
  22. data/spec/yelp/burst_struct_spec.rb +124 -0
  23. data/spec/yelp/client_spec.rb +75 -0
  24. data/spec/yelp/configuration_spec.rb +44 -0
  25. data/spec/yelp/endpoint/business_spec.rb +26 -0
  26. data/spec/yelp/endpoint/search_spec.rb +72 -0
  27. data/spec/yelp/error_spec.rb +22 -0
  28. data/spec/yelp/yelp_spec.rb +10 -0
  29. data/tasks/console.rake +4 -0
  30. data/yelp.gemspec +32 -0
  31. metadata +252 -90
  32. data/CHANGELOG.rdoc +0 -48
  33. data/Manifest.txt +0 -24
  34. data/README.rdoc +0 -118
  35. data/TODO.txt +0 -6
  36. data/lib/yelp/neighborhood/request/base.rb +0 -13
  37. data/lib/yelp/neighborhood/request/geo_point.rb +0 -23
  38. data/lib/yelp/neighborhood/request/location.rb +0 -53
  39. data/lib/yelp/phone/request/number.rb +0 -24
  40. data/lib/yelp/record.rb +0 -16
  41. data/lib/yelp/request.rb +0 -44
  42. data/lib/yelp/response_format.rb +0 -36
  43. data/lib/yelp/review/request/base.rb +0 -31
  44. data/lib/yelp/review/request/bounding_box.rb +0 -37
  45. data/lib/yelp/review/request/geo_point.rb +0 -28
  46. data/lib/yelp/review/request/location.rb +0 -63
  47. data/test/test_client.rb +0 -11
  48. data/test/test_neighborhood_search.rb +0 -46
  49. data/test/test_phone_search.rb +0 -20
  50. data/test/test_review_search.rb +0 -168
  51. data/test/yelp_helper.rb +0 -45
@@ -0,0 +1,152 @@
1
+ # yelp-ruby
2
+
3
+ This is a Ruby Gem for the Yelp API. It'll simplifies the process of consuming data from the Yelp API for developers using Ruby. The library encompasses both Search and Business API functions.
4
+
5
+ Please remember to read and follow the [Terms of Use](http://www.yelp.com/developers/getting_started/api_terms) and [display requirements](http://www.yelp.com/developers/getting_started/display_requirements) before creating your applications.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'yelp', require: 'yelp'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install yelp
20
+
21
+ ## Usage
22
+
23
+ ### Basic usage
24
+
25
+ The gem uses a client model to query against the API. You create and configure a client with your API keys and make requests through that.
26
+
27
+ ```
28
+ require 'yelp'
29
+
30
+ client = Yelp::Client.new({ consumer_key: YOUR_CONSUMER_KEY,
31
+ consumer_secret: YOUR_CONSUMER_SECRET,
32
+ token: YOUR_TOKEN,
33
+ token_secret: YOUR_TOKEN_SECRET
34
+ })
35
+ ```
36
+
37
+ Alternatively, you can also globally configure the client using a configure
38
+ block, and access a client singleton using `Yelp.client`. If you intend to
39
+ use the gem with Rails, the client should be configured in an initializer.
40
+
41
+ ```
42
+ require 'yelp'
43
+
44
+ Yelp.client.configure do |config|
45
+ config.consumer_key = YOUR_CONSUMER_KEY
46
+ config.consumer_secret = YOUR_CONSUMER_SECRET
47
+ config.token = YOUR_TOKEN
48
+ config.token_secret = YOUR_TOKEN_SECRET
49
+ end
50
+
51
+ Yelp.client.search('San Francisco', { term: 'food' })
52
+ ```
53
+
54
+ After creating the client you're able to make requests to either the Search API or Business API. Note: all four keys are required for making requests against the Yelp API. If you need any keys sign up and get access from [http://www.yelp.com/developers](http://www.yelp.com/developers).
55
+
56
+ ### [Search API](http://www.yelp.com/developers/documentation/v2/search_api)
57
+
58
+ Once you have a client you can use ``#search`` to make a request to the Search API.
59
+
60
+ ```
61
+ client.search('San Francisco')
62
+ ```
63
+
64
+ You can also pass in general params and locale options to the method as hashes
65
+
66
+ ```
67
+ params = { term: 'food',
68
+ limit: 3,
69
+ category_filter: 'discgolf'
70
+ }
71
+
72
+ locale = { lang: 'fr' }
73
+
74
+ client.search('San Francisco', params, locale)
75
+ ```
76
+
77
+ Key names and options for params and locale match the documented names on the [Yelp Search API](http://www.yelp.com/developers/documentation/v2/search_api)
78
+
79
+ Additionally there are two more search methods for searching by a [bounding box](http://www.yelp.com/developers/documentation/v2/search_api#searchGBB) or for [geographical coordinates](http://www.yelp.com/developers/documentation/v2/search_api#searchGC):
80
+
81
+ ```
82
+ # bounding box
83
+ bounding_box = { sw_latitude: 37.7577, sw_longitude: -122.4376, ne_latitude: 37.785381, ne_longitude: -122.391681 }
84
+ client.search_by_bounding_box(bounding_box, params, locale)
85
+
86
+ # coordinates
87
+ coordinates = { latitude: 37.7577, longitude: -122.4376 }
88
+ client.search_by_coordinates(coordinates, params, locale)
89
+ ```
90
+
91
+ ### [Business API](http://www.yelp.com/developers/documentation/v2/business)
92
+
93
+ To use the Business API after you have a client you just need to call ``#business`` with a business id
94
+
95
+ ```
96
+ client.business('yelp-san-francisco')
97
+ ```
98
+
99
+ You can pass in locale information as well
100
+
101
+ ```
102
+ locale = { lang: 'fr' }
103
+
104
+ client.business('yelp-san-francisco', locale)
105
+ ```
106
+
107
+ ## Responses
108
+
109
+ Responses from the API are all parsed and converted into Ruby objects. You're able to access information using dot-notation
110
+
111
+ ```
112
+ ## search
113
+ response = client.search('San Francisco')
114
+
115
+ response.businesses
116
+ # [<Business 1>, <Business 2>, ...]
117
+
118
+ response.businesses[0].name
119
+ # "Kim Makoi, DC"
120
+
121
+ response.businesses[0].rating
122
+ # 5.0
123
+
124
+
125
+ ## business
126
+ response = client.business('yelp-san-francisco')
127
+
128
+ response.name
129
+ # Yelp
130
+
131
+ response.categories
132
+ # [["Local Flavor", "localflavor"], ["Mass Media", "massmedia"]]
133
+ ```
134
+
135
+ For specific response values check out the docs for the [search api](http://www.yelp.com/developers/documentation/v2/search_api#rValue) and the [business api](http://www.yelp.com/developers/documentation/v2/business#rValue)
136
+
137
+ ## Contributing
138
+
139
+ 1. Fork it ( http://github.com/yelp/yelp-ruby/fork )
140
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
141
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
142
+ 4. Push to the branch (`git push origin my-new-feature`)
143
+ 5. Create new Pull Request
144
+
145
+ ### Git Workflow
146
+
147
+ We are using the [git flow](http://nvie.com/posts/a-successful-git-branching-model/)
148
+ workflow. Atlassian has a [solid overview](https://www.atlassian.com/git/workflows#!workflow-gitflow).
149
+ Essentially, new development is merged into the develop branch from feature
150
+ branches, then merged from develop to a release branch, then to master from
151
+ the release branch. Master should always contain the most recently released
152
+ version of the gem.
data/Rakefile CHANGED
@@ -1,25 +1,5 @@
1
- require 'rubygems'
2
- require 'hoe'
3
- $:.unshift(File.dirname(__FILE__) + "/lib")
4
- require 'yelp'
1
+ require "bundler/gem_tasks"
5
2
 
6
- Hoe.spec('yelp') do |p|
7
- self.version = Yelp::VERSION
8
- self.rubyforge_name = 'yelp'
9
- self.author = 'Walter Korman'
10
- self.email = 'shaper@fatgoose.com'
11
- self.extra_deps << [ 'json', '>= 1.1.1' ]
12
- self.summary = 'An object-oriented interface to the Yelp Developer API.'
13
- self.description = <<EDOC
14
- The yelp rubygem provides a Ruby object-oriented interface to the Yelp
15
- REST API described in detail at:
16
-
17
- http://www.yelp.com/developers/getting_started
18
- EDOC
19
- self.url = 'http://rubyforge.org/projects/yelp'
20
- self.changes = p.paragraphs_of('CHANGELOG.rdoc', 0..1).join("\n\n")
21
- self.remote_rdoc_dir = '' # Release to root
22
- self.readme_file = 'README.rdoc'
23
- self.history_file = 'CHANGELOG.rdoc'
24
- self.extra_rdoc_files = [ 'CHANGELOG.rdoc', 'README.rdoc' ]
25
- end
3
+ Dir["tasks/**/*.rake"].each do |file|
4
+ load(file)
5
+ end
@@ -1,16 +1,21 @@
1
+ require 'yelp/version'
1
2
  require 'yelp/client'
2
- require 'yelp/record'
3
- require 'yelp/request'
4
- require 'yelp/response_format'
5
- require 'yelp/neighborhood/request/base'
6
- require 'yelp/neighborhood/request/geo_point'
7
- require 'yelp/neighborhood/request/location'
8
- require 'yelp/phone/request/number'
9
- require 'yelp/review/request/base'
10
- require 'yelp/review/request/bounding_box'
11
- require 'yelp/review/request/geo_point'
12
- require 'yelp/review/request/location'
13
3
 
14
- class Yelp
15
- VERSION = '1.0.0'
4
+ module Yelp
5
+ # Returns an initially-unconfigured instance of the client.
6
+ # @return [Client] an instance of the client
7
+ #
8
+ # @example Configuring and using the client
9
+ # Yelp.client.configure do |config|
10
+ # config.consumer_key = 'abc'
11
+ # config.consumer_secret = 'def'
12
+ # config.token = 'ghi'
13
+ # config.token_secret = 'jkl'
14
+ # end
15
+ #
16
+ # Yelp.client.search('San Francisco', { term: 'food' })
17
+ #
18
+ def self.client
19
+ @client ||= Yelp::Client.new
20
+ end
16
21
  end
@@ -0,0 +1,51 @@
1
+ module BurstStruct
2
+ class Burst
3
+ def initialize(hash = {})
4
+ @hash = hash
5
+ end
6
+
7
+ def method_missing(method_name, *arguments, &block)
8
+ key = find_key(method_name)
9
+
10
+ if key
11
+ return_or_build_struct(key)
12
+ else
13
+ super
14
+ end
15
+ end
16
+
17
+ def respond_to?(method_name, include_private = false)
18
+ @hash.keys.include?(method_name) || super
19
+ end
20
+
21
+ def self.convert_array(array)
22
+ array.map do |item|
23
+ case item
24
+ when Hash
25
+ Burst.new(item)
26
+ when Array
27
+ Burst.convert_array(item)
28
+ else
29
+ item
30
+ end
31
+ end
32
+ end
33
+
34
+ def to_json(options = {})
35
+ JSON.generate(@hash)
36
+ end
37
+
38
+ private
39
+
40
+ def return_or_build_struct(method_name)
41
+ return Burst.new(@hash[method_name]) if @hash[method_name].is_a?(Hash)
42
+ return Burst.convert_array(@hash[method_name]) if @hash[method_name].is_a?(Array)
43
+ @hash[method_name]
44
+ end
45
+
46
+ def find_key(method_name)
47
+ return method_name.to_sym if @hash.keys.include? method_name.to_sym
48
+ return method_name.to_s if @hash.keys.include? method_name.to_s
49
+ end
50
+ end
51
+ end
@@ -1,105 +1,105 @@
1
- require 'cgi'
2
- require 'logger'
3
- require 'open-uri'
4
- require 'rubygems'
5
- require 'json'
6
- require 'yaml'
7
- require 'zlib'
1
+ require 'faraday'
2
+ require 'faraday_middleware'
8
3
 
9
- class Yelp
10
- # Provides access to the Yelp search facilities as documented at:
11
- #
12
- # http://www.yelp.com/developers/documentation
13
- #
14
- # Example usage:
15
- #
16
- # client = Yelp::Client.new
17
- # request = Yelp::Review::Request::Location.new(
18
- # :address => '650 Mission St',
19
- # :city => 'San Francisco',
20
- # :state => 'CA',
21
- # :radius => 2,
22
- # :term => 'cream puffs',
23
- # :yws_id => 'YOUR_YWSID_HERE')
24
- # response = client.search(request)
25
- #
26
- # By default, response content is formatted as a Ruby hash converted from
27
- # Yelp's source JSON response content. Alternate response formats can be
28
- # specified on request record construction via the Yelp::Request
29
- # +response_format+ parameter, available in all request record types.
30
- #
4
+ require 'yelp/burst_struct'
5
+ require 'yelp/configuration'
6
+ require 'yelp/error'
7
+ require 'yelp/endpoint/business'
8
+ require 'yelp/endpoint/search'
9
+
10
+ module Yelp
31
11
  class Client
32
- # allows specifying the user agent string to submit with search requests
33
- attr_accessor :agent
34
-
35
- # whether debug mode is enabled for logging purposes, defaulting to false
36
- attr_accessor :debug
37
-
38
- # the Logger compatible object with which log messages are outputted,
39
- # defaulting to output to STDOUT
40
- attr_accessor :logger
12
+ API_HOST = 'http://api.yelp.com'
13
+ REQUEST_CLASSES = [ Yelp::Endpoint::Search,
14
+ Yelp::Endpoint::Business ]
15
+
16
+ attr_reader :configuration
17
+
18
+ # Creates an instance of the Yelp client
19
+ # @param options [Hash, nil] a hash of the consumer key, consumer
20
+ # secret, token, and token secret
21
+ # @return [Client] a new client initialized with the keys
22
+ def initialize(options = nil)
23
+ @configuration = nil
24
+ define_request_methods
25
+
26
+ unless options.nil?
27
+ @configuration = Configuration.new(options)
28
+ check_api_keys
29
+ end
30
+ end
41
31
 
42
- # the default user agent submitted with search requests
43
- DEFAULT_AGENT = 'yelp for Ruby (http://www.rubyforge.org/projects/yelp/)'
32
+ # Configure the API client
33
+ # @yield [Configuration] a configuration object
34
+ # @raise [MissingAPIKeys] if the configuration is invalid
35
+ # @example Simple configuration
36
+ # Yelp.client.configure do |config|
37
+ # config.consumer_key = 'abc'
38
+ # config.consumer_secret = 'def'
39
+ # config.token = 'ghi'
40
+ # config.token_secret = 'jkl'
41
+ # end
42
+ def configure
43
+ raise AlreadyConfigured unless @configuration.nil?
44
44
 
45
- # Constructs a new client that uses the supplied YWSID for submitting
46
- # search requests.
47
- #
48
- def initialize
49
- @agent = DEFAULT_AGENT
50
- @debug = false
51
- @logger = nil
45
+ @configuration = Configuration.new
46
+ yield(@configuration)
47
+ check_api_keys
52
48
  end
53
-
54
- # Submits the supplied search request to Yelp and returns the response in
55
- # the format specified by the request.
56
- #
57
- def search (request)
58
- # build the full set of hash params with which the url is constructed
59
- params = request.to_yelp_params
60
49
 
61
- # construct the url with which we obtain results
62
- url = build_url(request.base_url, params)
63
- debug_msg "submitting search [url=#{url}, request=#{request.to_yaml}]."
50
+ # Checks that all the keys needed were given
51
+ def check_api_keys
52
+ if configuration.nil? || !configuration.valid?
53
+ @configuration = nil
54
+ raise MissingAPIKeys
55
+ else
56
+ # Freeze the configuration so it cannot be modified once the gem is
57
+ # configured. This prevents the configuration changing while the gem
58
+ # is operating, which would necessitate invalidating various caches.
59
+ @configuration.freeze
60
+ end
61
+ end
64
62
 
65
- # submit the http request for the results
66
- http_params = { 'User-Agent' => @agent }
67
- http_params['Accept-Encoding'] = 'gzip,deflate' if request.compress_response?
68
- source = open(url, http_params)
63
+ # API connection
64
+ def connection
65
+ return @connection if instance_variable_defined?(:@connection)
69
66
 
70
- # read the response content
71
- content = (request.compress_response?) ? Zlib::GzipReader.new(source).read : source.read
72
- debug_msg((request.response_format.serialized?) ? "received response [content_length=#{content.length}]." : "received response [content_length=#{content.length}, content=#{content}].")
67
+ check_api_keys
68
+ @connection = Faraday.new(API_HOST) do |conn|
69
+ # Use the Faraday OAuth middleware for OAuth 1.0 requests
70
+ conn.request :oauth, @configuration.auth_keys
73
71
 
74
- # format the output as specified in the request
75
- format_content(request.response_format, content)
72
+ # Using default http library, had to specify to get working
73
+ conn.adapter :net_http
74
+ end
76
75
  end
77
76
 
78
- protected
77
+ private
79
78
 
80
- def format_content (response_format, content)
81
- (response_format == Yelp::ResponseFormat::JSON_TO_RUBY) ? JSON.parse(content) : content
79
+ # This goes through each endpoint class and creates singletone methods
80
+ # on the client that query those classes. We do this to avoid possible
81
+ # namespace collisions in the future when adding new classes
82
+ def define_request_methods
83
+ REQUEST_CLASSES.each do |request_class|
84
+ endpoint_instance = request_class.new(self)
85
+ create_methods_from_instance(endpoint_instance)
82
86
  end
87
+ end
83
88
 
84
- def debug_msg (message)
85
- return if !@debug
86
- @logger = Logger.new(STDOUT) if (!@logger)
87
- @logger.debug message
89
+ # Loop through all of the endpoint instances' public singleton methods to
90
+ # add the method to client
91
+ def create_methods_from_instance(instance)
92
+ instance.public_methods(false).each do |method_name|
93
+ add_method(instance, method_name)
88
94
  end
95
+ end
89
96
 
90
- def build_url (base_url, params)
91
- url = base_url.clone
92
- url << '?'
93
- param_count = 0
94
- params.each do |key, value|
95
- next if value.nil?
96
- url << '&' if (param_count > 0)
97
- key_str = (params[key].kind_of?(Array)) ?
98
- params[key].map { |k| CGI.escape(k.to_s) }.join("+") : CGI.escape(params[key].to_s)
99
- url << "#{CGI.escape(key.to_s)}=#{key_str}"
100
- param_count += 1
101
- end
102
- url
97
+ # Define the method on the client and send it to the endpoint instance
98
+ # with the args passed in
99
+ def add_method(instance, method_name)
100
+ define_singleton_method(method_name) do |*args|
101
+ instance.public_send(method_name, *args)
103
102
  end
103
+ end
104
104
  end
105
105
  end