mapricot-api 0.5.0 → 0.6.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 +4 -4
- data/README.md +14 -14
- data/lib/mapricot/api.rb +84 -50
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca2609b68cb960b86372cdb41ecb1ad1f0880e0eabdd7995b605e49f64cdb8e3
|
|
4
|
+
data.tar.gz: 9037e3ac81b3e91f9389bc586f3dc1430a076cc6385347f3bb04615830745898
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c6845a3ae2301ab0368d2d943b891942127064b8b99565fbd4f16dfba3f2e2b5e95fc67e13312b538813107d0bf680035a66d061dc99c44066f220cc35de9b4e
|
|
7
|
+
data.tar.gz: 9c6dc48367361ab545b4c74c684da88d9886207f9e17ec5a61e1c9115dc801cf1129389f3f9d7425d4f51a3e72f97b47ff936c57a5006ef4d47fa34ffd4ef9fe
|
data/README.md
CHANGED
|
@@ -17,32 +17,32 @@ require "mapricot/api"
|
|
|
17
17
|
|
|
18
18
|
client = Mapricot::Client.new(api_key: ENV.fetch("MAPRICOT_KEY"))
|
|
19
19
|
|
|
20
|
-
data = client.search("128 SW 3rd Ave, Portland", limit: 1)
|
|
20
|
+
data = client.geocoding.search("128 SW 3rd Ave, Portland", limit: 1)
|
|
21
21
|
place = data["results"][0]
|
|
22
22
|
puts place["label"], place["lat"], place["lon"]
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Methods
|
|
26
26
|
|
|
27
|
-
Each
|
|
27
|
+
Methods are grouped by product, the same way as the API's paths. Each returns the API's JSON as a Hash with string keys, with the same field names as the [API reference](https://mapricot.com/api-reference/).
|
|
28
28
|
|
|
29
29
|
| Method | Endpoint |
|
|
30
30
|
| --- | --- |
|
|
31
|
-
| `client.search(q, focus:, country:, limit:, lang:)` | [`GET /geocoding/v1/search`](https://mapricot.com/docs/geocoding/#find-an-address) |
|
|
32
|
-
| `client.autocomplete(q, focus:, country:, limit:, lang:)` | [`GET /geocoding/v1/autocomplete`](https://mapricot.com/docs/geocoding/#suggest-as-people-type) |
|
|
33
|
-
| `client.reverse(lat, lon, limit:, lang:)` | [`GET /geocoding/v1/reverse`](https://mapricot.com/docs/geocoding/#find-the-address-at-a-point) |
|
|
34
|
-
| `client.nearby(lat, lon, category:, radius:, limit:, lang:)` | [`GET /places/v1/nearby`](https://mapricot.com/docs/places/#list-places-around-a-point) |
|
|
35
|
-
| `client.
|
|
36
|
-
| `client.route(waypoints, mode:, geometries:)` | [`POST /routing/v1/route`](https://mapricot.com/docs/routing/#get-a-route) |
|
|
37
|
-
| `client.isochrone(location, minutes, mode:)` | [`POST /routing/v1/isochrone`](https://mapricot.com/docs/routing/#get-an-isochrone) |
|
|
38
|
-
| `client.ip
|
|
31
|
+
| `client.geocoding.search(q, focus:, country:, limit:, lang:)` | [`GET /geocoding/v1/search`](https://mapricot.com/docs/geocoding/#find-an-address) |
|
|
32
|
+
| `client.geocoding.autocomplete(q, focus:, country:, limit:, lang:)` | [`GET /geocoding/v1/autocomplete`](https://mapricot.com/docs/geocoding/#suggest-as-people-type) |
|
|
33
|
+
| `client.geocoding.reverse(lat, lon, limit:, lang:)` | [`GET /geocoding/v1/reverse`](https://mapricot.com/docs/geocoding/#find-the-address-at-a-point) |
|
|
34
|
+
| `client.places.nearby(lat, lon, category:, radius:, limit:, lang:)` | [`GET /places/v1/nearby`](https://mapricot.com/docs/places/#list-places-around-a-point) |
|
|
35
|
+
| `client.places.get(id, lang:)` | [`GET /places/v1/{id}`](https://mapricot.com/docs/places/#look-up-a-saved-place) |
|
|
36
|
+
| `client.routing.route(waypoints, mode:, geometries:)` | [`POST /routing/v1/route`](https://mapricot.com/docs/routing/#get-a-route) |
|
|
37
|
+
| `client.routing.isochrone(location, minutes, mode:)` | [`POST /routing/v1/isochrone`](https://mapricot.com/docs/routing/#get-an-isochrone) |
|
|
38
|
+
| `client.ip_geolocation.lookup(ip)` | [`GET /ip-geolocation/v1/{ip}`](https://mapricot.com/docs/ip-geolocation/#look-up-an-address) |
|
|
39
39
|
| `client.account` | `GET /account`, which checks a key and is never billed |
|
|
40
40
|
|
|
41
41
|
Every keyword argument is optional. `focus` and each waypoint are `{ lat:, lon: }`. `country` and `category` take an Array or a comma-separated String.
|
|
42
42
|
|
|
43
43
|
```ruby
|
|
44
|
-
nearby = client.nearby(45.52, -122.68, category: ["food:coffee_shop"], radius: 1000)
|
|
45
|
-
route = client.route([{ lat: 45.5189, lon: -122.6793 }, { lat: 45.5214, lon: -122.6828 }], mode: "walk")
|
|
44
|
+
nearby = client.places.nearby(45.52, -122.68, category: ["food:coffee_shop"], radius: 1000)
|
|
45
|
+
route = client.routing.route([{ lat: 45.5189, lon: -122.6793 }, { lat: 45.5214, lon: -122.6828 }], mode: "walk")
|
|
46
46
|
puts route["routes"][0]["durationSeconds"]
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -51,7 +51,7 @@ A route's path comes as an encoded `polyline` with five decimal places, which po
|
|
|
51
51
|
An isochrone is a GeoJSON `FeatureCollection` with one polygon per time, largest first, so a map that draws them in order shows the smaller ones on top:
|
|
52
52
|
|
|
53
53
|
```ruby
|
|
54
|
-
area = client.isochrone({ lat: 45.5189, lon: -122.6793 }, [5, 10], mode: "walk")
|
|
54
|
+
area = client.routing.isochrone({ lat: 45.5189, lon: -122.6793 }, [5, 10], mode: "walk")
|
|
55
55
|
puts area["features"].map { |feature| feature["properties"]["minutes"] }.inspect
|
|
56
56
|
```
|
|
57
57
|
|
|
@@ -63,7 +63,7 @@ An error response raises `Mapricot::Error`, with the HTTP `status`, the API's er
|
|
|
63
63
|
|
|
64
64
|
```ruby
|
|
65
65
|
begin
|
|
66
|
-
client.search("")
|
|
66
|
+
client.geocoding.search("")
|
|
67
67
|
rescue Mapricot::Error => e
|
|
68
68
|
puts e.status, e.code, e.message # 400, invalid_request, The service rejected the request.
|
|
69
69
|
end
|
data/lib/mapricot/api.rb
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "erb"
|
|
3
4
|
require "json"
|
|
4
5
|
require "net/http"
|
|
5
6
|
|
|
6
7
|
# The official client for the Mapricot API: address and place search, reverse geocoding, nearby places, routing,
|
|
7
8
|
# and IP geolocation. See https://mapricot.com/docs/ruby/.
|
|
8
9
|
module Mapricot
|
|
9
|
-
VERSION = "0.
|
|
10
|
+
VERSION = "0.6.0"
|
|
10
11
|
|
|
11
12
|
# An error response from the API.
|
|
12
13
|
class Error < StandardError
|
|
@@ -20,8 +21,11 @@ module Mapricot
|
|
|
20
21
|
end
|
|
21
22
|
end
|
|
22
23
|
|
|
23
|
-
# Each
|
|
24
|
+
# Methods are grouped by product, as in client.geocoding.search. Each returns the API's JSON as a Hash with string
|
|
25
|
+
# keys, as in https://mapricot.com/api-reference/.
|
|
24
26
|
class Client
|
|
27
|
+
attr_reader :geocoding, :places, :routing, :ip_geolocation
|
|
28
|
+
|
|
25
29
|
def initialize(api_key:, base_url: "https://api.mapricot.com", timeout: 30, max_retries: 2)
|
|
26
30
|
raise ArgumentError, "Pass api_key:, a Mapricot key." if api_key.nil? || api_key.empty?
|
|
27
31
|
|
|
@@ -29,50 +33,10 @@ module Mapricot
|
|
|
29
33
|
@base_url = base_url
|
|
30
34
|
@timeout = timeout
|
|
31
35
|
@max_retries = max_retries
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
get("/geocoding/v1/search", q: q, focus: focus, country: country, limit: limit, lang: lang)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# Suggest addresses and places as someone types.
|
|
40
|
-
def autocomplete(q, focus: nil, country: nil, limit: nil, lang: nil)
|
|
41
|
-
get("/geocoding/v1/autocomplete", q: q, focus: focus, country: country, limit: limit, lang: lang)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Find the address nearest a coordinate, or the area around it.
|
|
45
|
-
def reverse(lat, lon, limit: nil, lang: nil)
|
|
46
|
-
get("/geocoding/v1/reverse", lat: lat, lon: lon, limit: limit, lang: lang)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# List places around a coordinate, optionally by category, an Array or a String.
|
|
50
|
-
def nearby(lat, lon, category: nil, radius: nil, limit: nil, lang: nil)
|
|
51
|
-
get("/places/v1/nearby", lat: lat, lon: lon, category: category, radius: radius, limit: limit, lang: lang)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Look up one place by its Mapricot ID.
|
|
55
|
-
def place(id, lang: nil)
|
|
56
|
-
get("/places/v1/#{escape(id)}", lang: lang)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# Find a route through 2 to 20 waypoints, each {lat:, lon:}. mode is "drive" (the default), "walk", or "bicycle".
|
|
60
|
-
# geometries is "polyline" (the default), "polyline6", or "geojson".
|
|
61
|
-
def route(waypoints, mode: nil, geometries: nil)
|
|
62
|
-
body = { waypoints: waypoints, mode: mode, geometries: geometries }.compact
|
|
63
|
-
request(Net::HTTP::Post, URI("#{@base_url}/routing/v1/route"), JSON.generate(body))
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# The areas reachable from a location, {lat:, lon:}, within 1 to 4 times, each 1 to 60 minutes, as a GeoJSON
|
|
67
|
-
# FeatureCollection with one polygon per time, largest first. mode is as for route.
|
|
68
|
-
def isochrone(location, minutes, mode: nil)
|
|
69
|
-
body = { location: location, minutes: minutes, mode: mode }.compact
|
|
70
|
-
request(Net::HTTP::Post, URI("#{@base_url}/routing/v1/isochrone"), JSON.generate(body))
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# Approximate location of a public IP address.
|
|
74
|
-
def ip(address)
|
|
75
|
-
get("/ip-geolocation/v1/#{escape(address)}")
|
|
36
|
+
@geocoding = GeocodingService.new(method(:get))
|
|
37
|
+
@places = PlacesService.new(method(:get))
|
|
38
|
+
@routing = RoutingService.new(method(:post))
|
|
39
|
+
@ip_geolocation = IpGeolocationService.new(method(:get))
|
|
76
40
|
end
|
|
77
41
|
|
|
78
42
|
# The key's account. Not billed, so it checks a key for free.
|
|
@@ -89,6 +53,10 @@ module Mapricot
|
|
|
89
53
|
request(Net::HTTP::Get, uri)
|
|
90
54
|
end
|
|
91
55
|
|
|
56
|
+
def post(path, body)
|
|
57
|
+
request(Net::HTTP::Post, URI(@base_url + path), JSON.generate(body.compact))
|
|
58
|
+
end
|
|
59
|
+
|
|
92
60
|
def request(method, uri, body = nil)
|
|
93
61
|
attempt = 0
|
|
94
62
|
loop do
|
|
@@ -121,10 +89,6 @@ module Mapricot
|
|
|
121
89
|
end
|
|
122
90
|
end
|
|
123
91
|
|
|
124
|
-
def escape(segment)
|
|
125
|
-
URI.encode_www_form_component(segment).gsub("+", "%20")
|
|
126
|
-
end
|
|
127
|
-
|
|
128
92
|
def error_from(response)
|
|
129
93
|
request_id = response["X-Request-Id"]
|
|
130
94
|
error = JSON.parse(response.body).fetch("error")
|
|
@@ -137,4 +101,74 @@ module Mapricot
|
|
|
137
101
|
error.status == 503 || error.code == "concurrency_exceeded"
|
|
138
102
|
end
|
|
139
103
|
end
|
|
104
|
+
|
|
105
|
+
# client.geocoding: the /geocoding/v1 endpoints.
|
|
106
|
+
class GeocodingService
|
|
107
|
+
def initialize(get)
|
|
108
|
+
@get = get
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Find addresses and places matching free text. focus is {lat:, lon:}; country is an Array or a String.
|
|
112
|
+
def search(q, focus: nil, country: nil, limit: nil, lang: nil)
|
|
113
|
+
@get.call("/geocoding/v1/search", q: q, focus: focus, country: country, limit: limit, lang: lang)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Suggest addresses and places as someone types.
|
|
117
|
+
def autocomplete(q, focus: nil, country: nil, limit: nil, lang: nil)
|
|
118
|
+
@get.call("/geocoding/v1/autocomplete", q: q, focus: focus, country: country, limit: limit, lang: lang)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Find the address nearest a coordinate, or the area around it.
|
|
122
|
+
def reverse(lat, lon, limit: nil, lang: nil)
|
|
123
|
+
@get.call("/geocoding/v1/reverse", lat: lat, lon: lon, limit: limit, lang: lang)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# client.places: the /places/v1 endpoints.
|
|
128
|
+
class PlacesService
|
|
129
|
+
def initialize(get)
|
|
130
|
+
@get = get
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# List places around a coordinate, optionally by category, an Array or a String.
|
|
134
|
+
def nearby(lat, lon, category: nil, radius: nil, limit: nil, lang: nil)
|
|
135
|
+
@get.call("/places/v1/nearby", lat: lat, lon: lon, category: category, radius: radius, limit: limit, lang: lang)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Look up one place by its Mapricot ID.
|
|
139
|
+
def get(id, lang: nil)
|
|
140
|
+
@get.call("/places/v1/#{ERB::Util.url_encode(id)}", lang: lang)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# client.routing: the /routing/v1 endpoints.
|
|
145
|
+
class RoutingService
|
|
146
|
+
def initialize(post)
|
|
147
|
+
@post = post
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Find a route through 2 to 20 waypoints, each {lat:, lon:}. mode is "drive" (the default), "walk", or "bicycle".
|
|
151
|
+
# geometries is "polyline" (the default), "polyline6", or "geojson".
|
|
152
|
+
def route(waypoints, mode: nil, geometries: nil)
|
|
153
|
+
@post.call("/routing/v1/route", { waypoints: waypoints, mode: mode, geometries: geometries })
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# The areas reachable from a location, {lat:, lon:}, within 1 to 4 times, each 1 to 60 minutes, as a GeoJSON
|
|
157
|
+
# FeatureCollection with one polygon per time, largest first. mode is as for route.
|
|
158
|
+
def isochrone(location, minutes, mode: nil)
|
|
159
|
+
@post.call("/routing/v1/isochrone", { location: location, minutes: minutes, mode: mode })
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# client.ip_geolocation: the /ip-geolocation/v1 endpoints.
|
|
164
|
+
class IpGeolocationService
|
|
165
|
+
def initialize(get)
|
|
166
|
+
@get = get
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Approximate location of a public IP address.
|
|
170
|
+
def lookup(ip)
|
|
171
|
+
@get.call("/ip-geolocation/v1/#{ERB::Util.url_encode(ip)}")
|
|
172
|
+
end
|
|
173
|
+
end
|
|
140
174
|
end
|