ohanakapa 1.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.
- 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
|