ohanakapa 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/lib/ohanakapa.rb +33 -0
  3. data/lib/ohanakapa/arguments.rb +14 -0
  4. data/lib/ohanakapa/authentication.rb +25 -0
  5. data/lib/ohanakapa/client.rb +226 -0
  6. data/lib/ohanakapa/client/categories.rb +42 -0
  7. data/lib/ohanakapa/client/keywords.rb +24 -0
  8. data/lib/ohanakapa/client/locations.rb +67 -0
  9. data/lib/ohanakapa/client/organizations.rb +43 -0
  10. data/lib/ohanakapa/client/rate_limit.rb +34 -0
  11. data/lib/ohanakapa/client/search.rb +23 -0
  12. data/lib/ohanakapa/configurable.rb +78 -0
  13. data/lib/ohanakapa/default.rb +88 -0
  14. data/lib/ohanakapa/error.rb +130 -0
  15. data/lib/ohanakapa/rate_limit.rb +31 -0
  16. data/lib/ohanakapa/response/raise_error.rb +21 -0
  17. data/lib/ohanakapa/version.rb +6 -0
  18. data/spec/cassettes/Ohanakapa_Client/_get/handles_query_params.json +1 -0
  19. data/spec/cassettes/Ohanakapa_Client/_head/handles_query_params.json +1 -0
  20. data/spec/cassettes/Ohanakapa_Client/_last_response/caches_the_last_agent_response.json +1 -0
  21. data/spec/cassettes/Ohanakapa_Client/auto_pagination/fetches_all_the_pages.json +1 -0
  22. data/spec/cassettes/Ohanakapa_Client_Categories/_add_keywords_to_a_service/adds_keywords_to_a_given_service.json +1 -0
  23. data/spec/cassettes/Ohanakapa_Client_Categories/_categories/returns_all_categories.json +1 -0
  24. data/spec/cassettes/Ohanakapa_Client_Categories/_replace_all_categories/replaces_all_categories_for_a_service.json +1 -0
  25. data/spec/cassettes/Ohanakapa_Client_Locations/_location/returns_an_location.json +1 -0
  26. data/spec/cassettes/Ohanakapa_Client_Locations/_locations/returns_all_locations.json +1 -0
  27. data/spec/cassettes/Ohanakapa_Client_Locations/_nearby/returns_locations_near_the_queried_location.json +1 -0
  28. data/spec/cassettes/Ohanakapa_Client_Locations/_update_location/updates_a_location_s_attributes.json +1 -0
  29. data/spec/cassettes/Ohanakapa_Client_Organizations/_organization/returns_an_organization.json +1 -0
  30. data/spec/cassettes/Ohanakapa_Client_Organizations/_organizations/returns_all_organizations.json +1 -0
  31. data/spec/cassettes/Ohanakapa_Client_Search/_search/searches_for_keyword_food_and_language_Spanish_.json +1 -0
  32. data/spec/cassettes/Ohanakapa_Client_Search/_search/searches_for_keyword_market_.json +1 -0
  33. data/spec/cassettes/Ohanakapa_Client_Search/_search/searches_for_location_san_mateo_ca_.json +1 -0
  34. data/spec/cassettes/rate_limit.json +1 -0
  35. data/spec/cassettes/root.json +1 -0
  36. data/spec/ohanakapa/client/categories_spec.rb +27 -0
  37. data/spec/ohanakapa/client/keywords_spec.rb +20 -0
  38. data/spec/ohanakapa/client/locations_spec.rb +41 -0
  39. data/spec/ohanakapa/client/organizations_spec.rb +23 -0
  40. data/spec/ohanakapa/client/rate_limit_spec.rb +40 -0
  41. data/spec/ohanakapa/client/search_spec.rb +38 -0
  42. data/spec/ohanakapa/client_spec.rb +363 -0
  43. data/spec/ohanakapa/rate_limit_spec.rb +25 -0
  44. data/spec/ohanakapa_spec.rb +46 -0
  45. data/spec/spec_helper.rb +88 -0
  46. metadata +146 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6afd9df44e4e14d0effab2bd786c6403b0bacb8d
4
+ data.tar.gz: 67e060430cb70d065cb082eecc7fd4d843831417
5
+ SHA512:
6
+ metadata.gz: 6cc26a543d2d073213bebb5d47efeb957670feb0e37c7b4e28dcc6c4bca1d534b402ac5027f8e4fede437ebe5b5f42c947d17ec4645470baa1a4d10ce634f5f6
7
+ data.tar.gz: 89fefdb5dec09c5116a98ba899c6e990e75d04c591b1c9d9caab39265d1c9ba75280a50a15307800911e9b130c8f34cf5df8f9e4f67c6b0a0f836596a6fd25ee
@@ -0,0 +1,33 @@
1
+ require 'ohanakapa/client'
2
+ require 'ohanakapa/default'
3
+
4
+ # Ruby toolkit for the Ohana API
5
+ module Ohanakapa
6
+
7
+ class << self
8
+ include Ohanakapa::Configurable
9
+
10
+ # API client based on configured options {Configurable}
11
+ #
12
+ # @return [Ohanakapa::Client] API wrapper
13
+ def client
14
+ @client = Ohanakapa::Client.new(options) unless defined?(@client) && @client.same_options?(options)
15
+ @client
16
+ end
17
+
18
+ # @private
19
+ def respond_to_missing?(method_name, include_private=false); client.respond_to?(method_name, include_private); end if RUBY_VERSION >= "1.9"
20
+ # @private
21
+ def respond_to?(method_name, include_private=false); client.respond_to?(method_name, include_private) || super; end if RUBY_VERSION < "1.9"
22
+
23
+ private
24
+
25
+ def method_missing(method_name, *args, &block)
26
+ return super unless client.respond_to?(method_name)
27
+ client.send(method_name, *args, &block)
28
+ end
29
+
30
+ end
31
+ end
32
+
33
+ Ohanakapa.setup
@@ -0,0 +1,14 @@
1
+ module Ohanakapa
2
+
3
+ # Extracts options from method arguments
4
+ # @private
5
+ class Arguments < Array
6
+ attr_reader :options
7
+
8
+ def initialize(args)
9
+ @options = args.last.is_a?(::Hash) ? args.pop : {}
10
+ super(args)
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ module Ohanakapa
2
+
3
+ # Authentication methods for {Ohanakapa::Client}
4
+ module Authentication
5
+
6
+ # Indicates if the client has Application
7
+ # api_token credentials to make anonymous
8
+ # requests at a higher rate limit
9
+ #
10
+ # @see http://ohanapi.herokuapp.com/api/docs
11
+ # @return [Boolean]
12
+ def application_authenticated?
13
+ !!application_authentication
14
+ end
15
+
16
+ private
17
+
18
+ def application_authentication
19
+ if @api_token
20
+ { :api_token => @api_token }
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,226 @@
1
+ require 'sawyer'
2
+ require 'ohanakapa/arguments'
3
+ require 'ohanakapa/configurable'
4
+ require 'ohanakapa/authentication'
5
+ require 'ohanakapa/rate_limit'
6
+ require 'ohanakapa/client/organizations'
7
+ require 'ohanakapa/client/locations'
8
+ require 'ohanakapa/client/categories'
9
+ require 'ohanakapa/client/keywords'
10
+ require 'ohanakapa/client/search'
11
+ require 'ohanakapa/client/rate_limit'
12
+
13
+ module Ohanakapa
14
+
15
+ # Client for the Ohana API
16
+ #
17
+ # @see http://ohanapi.herokuapp.com/api/docs
18
+ class Client
19
+
20
+ include Ohanakapa::Authentication
21
+ include Ohanakapa::Configurable
22
+ include Ohanakapa::Client::Organizations
23
+ include Ohanakapa::Client::Locations
24
+ include Ohanakapa::Client::Categories
25
+ include Ohanakapa::Client::Keywords
26
+ include Ohanakapa::Client::Search
27
+ include Ohanakapa::Client::RateLimit
28
+
29
+ # Header keys that can be passed in options hash to {#get},{#head}
30
+ CONVENIENCE_HEADERS = Set.new [:accept]
31
+
32
+ def initialize(options = {})
33
+ # Use options passed in, but fall back to module defaults
34
+ Ohanakapa::Configurable.keys.each do |key|
35
+ instance_variable_set(:"@#{key}", options[key] || Ohanakapa.instance_variable_get(:"@#{key}"))
36
+ end
37
+ end
38
+
39
+ # Compares client options to a Hash of requested options
40
+ #
41
+ # @param opts [Hash] Options to compare with current client options
42
+ # @return [Boolean]
43
+ def same_options?(opts)
44
+ opts.hash == options.hash
45
+ end
46
+
47
+ # Text representation of the client, masking tokens and passwords
48
+ #
49
+ # @return [String]
50
+ def inspect
51
+ inspected = super
52
+
53
+ # Only show last 4 of api token
54
+ if @api_token
55
+ inspected = inspected.gsub! @api_token, "#{'*'*32}#{@api_token[32..-1]}"
56
+ end
57
+
58
+ inspected
59
+ end
60
+
61
+ # Make a HTTP GET request
62
+ #
63
+ # @param url [String] The path, relative to {#api_endpoint}
64
+ # @param options [Hash] Query and header params for request
65
+ # @return [Sawyer::Resource]
66
+ def get(url, options = {})
67
+ request :get, url, parse_query_and_convenience_headers(options)
68
+ end
69
+
70
+ # Make a HTTP POST request
71
+ #
72
+ # @param url [String] The path, relative to {#api_endpoint}
73
+ # @param options [Hash] Body and header params for request
74
+ # @return [Sawyer::Resource]
75
+ def post(url, options = {})
76
+ request :post, url, options
77
+ end
78
+
79
+
80
+ # Make a HTTP PUT request
81
+ #
82
+ # @param url [String] The path, relative to {#api_endpoint}
83
+ # @param options [Hash] Body and header params for request
84
+ # @return [Sawyer::Resource]
85
+ def put(url, options = {})
86
+ request :put, url, options
87
+ end
88
+
89
+ # Make a HTTP PATCH request
90
+ #
91
+ # @param url [String] The path, relative to {#api_endpoint}
92
+ # @param options [Hash] Body and header params for request
93
+ # @return [Sawyer::Resource]
94
+ def patch(url, options = {})
95
+ request :patch, url, options
96
+ end
97
+
98
+ # Make a HTTP DELETE request
99
+ #
100
+ # @param url [String] The path, relative to {#api_endpoint}
101
+ # @param options [Hash] Query and header params for request
102
+ # @return [Sawyer::Resource]
103
+ def delete(url, options = {})
104
+ request :delete, url, options
105
+ end
106
+
107
+ # Make a HTTP HEAD request
108
+ #
109
+ # @param url [String] The path, relative to {#api_endpoint}
110
+ # @param options [Hash] Query and header params for request
111
+ # @return [Sawyer::Resource]
112
+ def head(url, options = {})
113
+ request :head, url, parse_query_and_convenience_headers(options)
114
+ end
115
+
116
+ # Make one or more HTTP GET requests, optionally fetching
117
+ # the next page of results from URL in Link response header based
118
+ # on value in {#auto_paginate}.
119
+ #
120
+ # @param url [String] The path, relative to {#api_endpoint}
121
+ # @param options [Hash] Query and header params for request
122
+ # @return [Sawyer::Resource]
123
+ def paginate(url, options = {})
124
+ opts = parse_query_and_convenience_headers(options.dup)
125
+ # if @auto_paginate
126
+ # opts[:query][:per_page] ||= @per_page || (@auto_paginate ? 100 : nil)
127
+ # end
128
+
129
+ data = request(:get, url, opts)
130
+
131
+ if @auto_paginate && data.is_a?(Array)
132
+ while @last_response.rels[:next] && rate_limit.remaining > 0
133
+ @last_response = @last_response.rels[:next].get
134
+ data.concat(@last_response.data) if @last_response.data.is_a?(Array)
135
+ end
136
+
137
+ end
138
+
139
+ data
140
+ end
141
+
142
+ # Hypermedia agent for the Ohana API
143
+ #
144
+ # @return [Sawyer::Agent]
145
+ def agent
146
+ @agent ||= Sawyer::Agent.new(api_endpoint, sawyer_options) do |http|
147
+ http.headers[:accept] = default_media_type
148
+ http.headers[:user_agent] = user_agent
149
+ if application_authenticated?
150
+ http.headers["X-Api-Token"] = @api_token
151
+ end
152
+ end
153
+ end
154
+
155
+ # Fetch the root resource for the API
156
+ #
157
+ # @return [Sawyer::Resource]
158
+ def root
159
+ agent.start.data
160
+ end
161
+
162
+ # Response for last HTTP request
163
+ #
164
+ # @return [Sawyer::Response]
165
+ def last_response
166
+ @last_response
167
+ end
168
+
169
+ private
170
+
171
+ def request(method, path, data)
172
+ options = {}
173
+ options[:query] = data.delete(:query) || {}
174
+ options[:headers] = data.delete(:headers) || {}
175
+
176
+ if application_authenticated?
177
+ options[:query].merge! application_authentication
178
+ end
179
+ if accept = data.delete(:accept)
180
+ options[:headers][:accept] = accept
181
+ end
182
+
183
+ @last_response = response = agent.call(method, URI.encode(path), data, options)
184
+ response.data
185
+ end
186
+
187
+ # Executes the request, checking if it was successful
188
+ #
189
+ # @return [Boolean] True on success, false otherwise
190
+ def boolean_from_response(method, path, options = {})
191
+ request(method, path, options)
192
+ @last_response.status == 204
193
+ rescue Ohanakapa::NotFound
194
+ false
195
+ end
196
+
197
+
198
+ def sawyer_options
199
+ opts = {
200
+ :links_parser => Sawyer::LinkParsers::Simple.new
201
+ }
202
+ conn_opts = @connection_options
203
+ conn_opts[:builder] = @middleware if @middleware
204
+ conn_opts[:proxy] = @proxy if @proxy
205
+ opts[:faraday] = Faraday.new(conn_opts)
206
+
207
+ opts
208
+ end
209
+
210
+ def parse_query_and_convenience_headers(options)
211
+ headers = options.fetch(:headers, {})
212
+ CONVENIENCE_HEADERS.each do |h|
213
+ if header = options.delete(h)
214
+ headers[h] = header
215
+ end
216
+ end
217
+ query = options.delete(:query)
218
+ opts = {:query => options}
219
+ opts[:query].merge!(query) if query && query.is_a?(Hash)
220
+ opts[:headers] = headers unless headers.empty?
221
+
222
+ opts
223
+ end
224
+
225
+ end
226
+ end
@@ -0,0 +1,42 @@
1
+ module Ohanakapa
2
+ class Client
3
+
4
+ # Methods for the Categories endpoint
5
+ #
6
+ # @see http://ohanapi.herokuapp.com/api/docs
7
+ module Categories
8
+
9
+ # List all categories
10
+ #
11
+ # This provides a dump of every category, in the order that they
12
+ # were uploaded to the Ohana DB.
13
+ #
14
+ # @see http://ohanapi.herokuapp.com/api/docs#!/api/GET-api-categories---format-_get_0
15
+ #
16
+ # @return [Array<Sawyer::Resource>] List of Categories.
17
+ #
18
+ # @example
19
+ # Ohanakapa.categories
20
+ # @example
21
+ # Ohanakapa.cats
22
+ def categories(options={})
23
+ paginate "categories", options
24
+ end
25
+ alias :cats :categories
26
+
27
+ # Replace all categories for a Service
28
+ #
29
+ # @param service_id [String] Number ID of the service
30
+ # @param cat_ids [Array] An array of category IDs to use as replacement
31
+ # @return [<Sawyer::Resource>] The updated service
32
+ # @see http://ohanapi.herokuapp.com/api/docs
33
+ # @example Replace categories for service with ID '521d339f1974fcdb2b00573e'
34
+ # Ohanakapa.replace_all_categories("521d339f1974fcdb2b00573e", ['52280f5c1edd37edff000001', '52280f5c1edd37edff000003'])
35
+ def replace_all_categories(service_id, cat_ids)
36
+ put "services/#{service_id}/categories", :query => { :category_ids => cat_ids }
37
+ end
38
+
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,24 @@
1
+ module Ohanakapa
2
+ class Client
3
+
4
+ # Methods for adding Keywords to a service
5
+ #
6
+ # @see http://ohanapi.herokuapp.com/api/docs
7
+ module Keywords
8
+
9
+ # Add keywords to a Service
10
+ #
11
+ # @param service_id [String] Number ID of the service
12
+ # @param keywords [Array] An array of keywords to use as replacement
13
+ # @return [<Sawyer::Resource>] The updated service
14
+ # @see http://ohanapi.herokuapp.com/api/docs
15
+ # @example Add keywords to service with ID '521d339f1974fcdb2b00573e'
16
+ # Ohanakapa.add_keywords_to_a_service("521d339f1974fcdb2b00573e", ['testing', 'api'])
17
+ def add_keywords_to_a_service(service_id, keywords)
18
+ post "services/#{service_id}/keywords", :query => { :keywords => keywords }
19
+ end
20
+
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,67 @@
1
+ module Ohanakapa
2
+ class Client
3
+
4
+ # Methods for the Locations API
5
+ #
6
+ # @see http://ohanapi.herokuapp.com/api/docs
7
+ module Locations
8
+
9
+ # List all locations
10
+ #
11
+ # This provides a dump of every location, in the order that they
12
+ # were uploaded to the Ohana DB.
13
+ #
14
+ # @see http://ohanapi.herokuapp.com/api/docs#!/api/GET-api-locations---format-_get_0
15
+ #
16
+ # @return [Array<Sawyer::Resource>] List of Locations.
17
+ #
18
+ # @example
19
+ # Ohanakapa.locations
20
+ # @example
21
+ # Ohanakapa.locs
22
+ def locations(options={})
23
+ paginate "locations", options
24
+ end
25
+ alias :locs :locations
26
+
27
+ # Get a single location based on its ID
28
+ # @see http://ohanapi.herokuapp.com/api/docs#!/api/GET-api-locations--id---format-_get_1
29
+ #
30
+ # @param id [String] location ID.
31
+ # @return [Sawyer::Resource]
32
+ # @example
33
+ # Ohanakapa.location('519c44065634241897000023')
34
+ # @example
35
+ # Ohanakapa.loc('519c44065634241897000023')
36
+ def location(id)
37
+ get("locations/#{id}")
38
+ end
39
+ alias :loc :location
40
+
41
+ # Get nearby locations to an location, based on its ID
42
+ #
43
+ # @param id [String] location ID.
44
+ # @param options [Hash] A customizable set of options.
45
+ # @option options [Float] :radius
46
+ # @return [Sawyer::Resource] Hash representing nearby locations.
47
+ # @example
48
+ # Ohanakapa.nearby('519c44065634241897000023', :radius => 0.5)
49
+ def nearby(id, options={})
50
+ get("locations/#{id}/nearby", options)
51
+ end
52
+
53
+ # Update a location
54
+ #
55
+ # @param id [String] location ID.
56
+ # @param options [Hash] A customizable set of options.
57
+ # @option options [String] :kind
58
+ # @return [Sawyer::Resource]
59
+ # @example
60
+ # Ohanakapa.location("521d33a01974fcdb2b0036a9", :kind => "entertainment")
61
+ def update_location(id, options)
62
+ put "locations/#{id}", :query => options
63
+ end
64
+
65
+ end
66
+ end
67
+ end