ohanakapa 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/ohanakapa.rb +33 -0
- data/lib/ohanakapa/arguments.rb +14 -0
- data/lib/ohanakapa/authentication.rb +25 -0
- data/lib/ohanakapa/client.rb +226 -0
- data/lib/ohanakapa/client/categories.rb +42 -0
- data/lib/ohanakapa/client/keywords.rb +24 -0
- data/lib/ohanakapa/client/locations.rb +67 -0
- data/lib/ohanakapa/client/organizations.rb +43 -0
- data/lib/ohanakapa/client/rate_limit.rb +34 -0
- data/lib/ohanakapa/client/search.rb +23 -0
- data/lib/ohanakapa/configurable.rb +78 -0
- data/lib/ohanakapa/default.rb +88 -0
- data/lib/ohanakapa/error.rb +130 -0
- data/lib/ohanakapa/rate_limit.rb +31 -0
- data/lib/ohanakapa/response/raise_error.rb +21 -0
- data/lib/ohanakapa/version.rb +6 -0
- data/spec/cassettes/Ohanakapa_Client/_get/handles_query_params.json +1 -0
- data/spec/cassettes/Ohanakapa_Client/_head/handles_query_params.json +1 -0
- data/spec/cassettes/Ohanakapa_Client/_last_response/caches_the_last_agent_response.json +1 -0
- data/spec/cassettes/Ohanakapa_Client/auto_pagination/fetches_all_the_pages.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Categories/_add_keywords_to_a_service/adds_keywords_to_a_given_service.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Categories/_categories/returns_all_categories.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Categories/_replace_all_categories/replaces_all_categories_for_a_service.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Locations/_location/returns_an_location.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Locations/_locations/returns_all_locations.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Locations/_nearby/returns_locations_near_the_queried_location.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Locations/_update_location/updates_a_location_s_attributes.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Organizations/_organization/returns_an_organization.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Organizations/_organizations/returns_all_organizations.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Search/_search/searches_for_keyword_food_and_language_Spanish_.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Search/_search/searches_for_keyword_market_.json +1 -0
- data/spec/cassettes/Ohanakapa_Client_Search/_search/searches_for_location_san_mateo_ca_.json +1 -0
- data/spec/cassettes/rate_limit.json +1 -0
- data/spec/cassettes/root.json +1 -0
- data/spec/ohanakapa/client/categories_spec.rb +27 -0
- data/spec/ohanakapa/client/keywords_spec.rb +20 -0
- data/spec/ohanakapa/client/locations_spec.rb +41 -0
- data/spec/ohanakapa/client/organizations_spec.rb +23 -0
- data/spec/ohanakapa/client/rate_limit_spec.rb +40 -0
- data/spec/ohanakapa/client/search_spec.rb +38 -0
- data/spec/ohanakapa/client_spec.rb +363 -0
- data/spec/ohanakapa/rate_limit_spec.rb +25 -0
- data/spec/ohanakapa_spec.rb +46 -0
- data/spec/spec_helper.rb +88 -0
- metadata +146 -0
checksums.yaml
ADDED
@@ -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
|
data/lib/ohanakapa.rb
ADDED
@@ -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,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
|