geocodio 1.0.1 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e30b7374e1e8cb776ab35c399696392474e1c1a8
4
- data.tar.gz: e6959a9f46466860519c940139d7550a18bf5725
3
+ metadata.gz: 527dfc5568d5e04687a5e77ed4be5a618f63d1f0
4
+ data.tar.gz: 511078ee7c3cfbd7d8002faf2b1e35fef9f8da3d
5
5
  SHA512:
6
- metadata.gz: 86466ddda70124ebe8d17e5d6db87d4f043988b1b5a98e1071d016f23cca04ef1dc3d2b5e844b924f3076124f32f9db6d94c88a5ef71ca738abaf85cd02f9520
7
- data.tar.gz: 0974281a783423bb1d97a866c5192a46dd7dbe54ede8aa979deed2d1daa38b814e698415cc882b74433ece98d1686d873a8451d624f6e5f71c66631989bacf4f
6
+ metadata.gz: ccc773caf2885c4801dd40b647e97b092830349f43fcea0a125325fa9be308da0faaef6416a01de3675b4d9f36ee6cbcf8718815774a3c1d895950d2b776c1ce
7
+ data.tar.gz: cffce0a8438f2016369ad80a839987941e45fccdb5aabc2490dc4499813da0731ad54f37989ceb8f0bac6f9b30dd289074c201516d2a284beccd793308e3e287
@@ -4,9 +4,12 @@ require 'cgi'
4
4
 
5
5
  require 'geocodio/client/error'
6
6
  require 'geocodio/client/response'
7
+ require 'geocodio/utils'
7
8
 
8
9
  module Geocodio
9
10
  class Client
11
+ include Geocodio::Utils
12
+
10
13
  CONTENT_TYPE = 'application/json'
11
14
  METHODS = {
12
15
  :get => Net::HTTP::Get,
@@ -26,7 +29,7 @@ module Geocodio
26
29
  # is submitted to http://api.geocod.io/v1/geocode. Multiple addresses will
27
30
  # instead submit a POST request.
28
31
  #
29
- # @param addresses [Array] one or more String addresses
32
+ # @param addresses [Array<String>] one or more String addresses
30
33
  # @return [Geocodio::Address, Array<Geocodio::AddressSet>] One or more Address Sets
31
34
  def geocode(*addresses)
32
35
  addresses = addresses.first if addresses.first.is_a?(Array)
@@ -40,6 +43,28 @@ module Geocodio
40
43
  end
41
44
  end
42
45
 
46
+ # Reverse geocodes one or more pairs of coordinates. Coordinate pairs may be
47
+ # specified either as a comma-separated "latitude,longitude" string, or as
48
+ # a Hash with :lat/:latitude and :lng/:longitude keys. If one pair of
49
+ # coordinates is specified, a GET request is submitted to
50
+ # http://api.geocod.io/v1/reverse. Multiple pairs of coordinates will
51
+ # instead submit a POST request.
52
+ #
53
+ # @param coordinates [Array<String>, Array<Hash>] one or more pairs of coordinates
54
+ # @return [Geocodio::Address, Array<Geocodio::AddressSet>] One or more Address Sets
55
+ def reverse_geocode(*coordinates)
56
+ coordinates = coordinates.first if coordinates.first.is_a?(Array)
57
+
58
+ if coordinates.size < 1
59
+ raise ArgumentError, 'You must provide coordinates to reverse geocode.'
60
+ elsif coordinates.size == 1
61
+ reverse_geocode_single(coordinates.first)
62
+ else
63
+ reverse_geocode_batch(coordinates)
64
+ end
65
+ end
66
+ alias :reverse :reverse_geocode
67
+
43
68
  # Sends a GET request to http://api.geocod.io/v1/parse to correctly dissect
44
69
  # an address into individual parts. As this endpoint does not do any
45
70
  # geocoding, parts missing from the passed address will be missing from the
@@ -61,24 +86,31 @@ module Geocodio
61
86
 
62
87
  def geocode_single(address)
63
88
  response = get '/geocode', q: address
64
- results = response.body['results']
65
- query = response.body['input']['formatted_address']
66
- addresses = results.map { |result| Address.new(result) }
89
+ addresses = parse_results(response)
90
+
91
+ AddressSet.new(address, *addresses)
92
+ end
93
+
94
+ def reverse_geocode_single(pair)
95
+ pair = normalize_coordinates(pair)
67
96
 
68
- AddressSet.new(query, *addresses)
97
+ response = get '/reverse', q: pair
98
+ addresses = parse_results(response)
99
+
100
+ AddressSet.new(pair, *addresses)
69
101
  end
70
102
 
71
103
  def geocode_batch(addresses)
72
- response = post '/geocode', {}, body: addresses
73
- result_sets = response.body['results']
104
+ response = post '/geocode', {}, body: addresses
105
+
106
+ parse_nested_results(response)
107
+ end
74
108
 
75
- result_sets.map do |result_set|
76
- query = result_set['response']['input']['formatted_address']
77
- results = result_set['response']['results']
78
- addresses = results.map { |result| Address.new(result) }
109
+ def reverse_geocode_batch(pairs)
110
+ pairs.map! { |pair| normalize_coordinates(pair) }
111
+ response = post '/reverse', {}, body: pairs
79
112
 
80
- AddressSet.new(query, *addresses)
81
- end
113
+ parse_nested_results(response)
82
114
  end
83
115
 
84
116
  def request(method, path, options)
@@ -0,0 +1,26 @@
1
+ module Geocodio
2
+ module Utils
3
+ def parse_results(response)
4
+ results = response.body['results']
5
+ addresses = results.map { |result| Address.new(result) }
6
+ end
7
+
8
+ def parse_nested_results(response)
9
+ results = response.body['results']
10
+
11
+ results.map do |result_set|
12
+ results = result_set['response']['results']
13
+ addresses = results.map { |result| Address.new(result) }
14
+
15
+ query = result_set['query']
16
+
17
+ AddressSet.new(query, *addresses)
18
+ end
19
+ end
20
+
21
+ def normalize_coordinates(coordinates)
22
+ return coordinates unless coordinates.is_a?(Hash)
23
+ coordinates.sort.map { |p| p[1] }.join(',')
24
+ end
25
+ end
26
+ end
@@ -1,8 +1,8 @@
1
1
  module Geocodio
2
2
  class Version
3
3
  MAJOR = 1
4
- MINOR = 0
5
- PATCH = 1
4
+ MINOR = 1
5
+ PATCH = 0
6
6
 
7
7
  def self.to_s
8
8
  [MAJOR, MINOR, PATCH].join('.')
@@ -26,6 +26,6 @@ describe Geocodio::AddressSet do
26
26
  end
27
27
 
28
28
  it 'references the original query' do
29
- expect(address_set.query).to eq('826 Howard St, San Francisco CA, 94103')
29
+ expect(address_set.query).to eq('826 Howard Street San Francisco CA 94103')
30
30
  end
31
31
  end
@@ -1,8 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Geocodio::Client do
4
- let(:geocodio) { Geocodio::Client.new }
5
- let(:address) { '54 West Colorado Boulevard Pasadena CA 91105' }
4
+ let(:geocodio) { Geocodio::Client.new }
5
+ let(:address) { '54 West Colorado Boulevard Pasadena CA 91105' }
6
+ let(:coordinates) { '34.145760590909,-118.15204363636' }
6
7
 
7
8
  it 'requires an API key' do
8
9
  VCR.use_cassette('invalid_key') do
@@ -27,6 +28,27 @@ describe Geocodio::Client do
27
28
  end
28
29
  end
29
30
 
31
+ context 'reverse geocoding a single address' do
32
+ it 'uses a string' do
33
+ VCR.use_cassette('reverse') do
34
+ addresses = geocodio.reverse_geocode(coordinates)
35
+
36
+ expect(addresses.size).to eq(3)
37
+ expect(addresses).to be_a(Geocodio::AddressSet)
38
+ end
39
+ end
40
+
41
+ it 'uses a hash' do
42
+ VCR.use_cassette('reverse') do
43
+ lat, lng = coordinates.split(',')
44
+ addresses = geocodio.reverse_geocode(latitude: lat, longitude: lng)
45
+
46
+ expect(addresses.size).to eq(3)
47
+ expect(addresses).to be_a(Geocodio::AddressSet)
48
+ end
49
+ end
50
+ end
51
+
30
52
  it 'geocodes multiple addresses' do
31
53
  VCR.use_cassette('batch_geocode') do
32
54
  addresses = [
@@ -41,4 +63,51 @@ describe Geocodio::Client do
41
63
  addresses.each { |address| expect(address).to be_a(Geocodio::AddressSet) }
42
64
  end
43
65
  end
66
+
67
+ context 'reverse geocoding multiple addresses' do
68
+ it 'uses strings' do
69
+ VCR.use_cassette('batch_reverse') do
70
+ coordinate_pairs = [
71
+ '37.331669,-122.03074',
72
+ '34.145760590909,-118.15204363636',
73
+ '37.7815,-122.404933'
74
+ ]
75
+
76
+ addresses = geocodio.reverse_geocode(*coordinate_pairs)
77
+
78
+ expect(addresses.size).to eq(3)
79
+ addresses.each { |address| expect(address).to be_a(Geocodio::AddressSet) }
80
+ end
81
+ end
82
+
83
+ it 'uses hashes' do
84
+ VCR.use_cassette('batch_reverse') do
85
+ coordinate_pairs = [
86
+ { latitude: 37.331669, longitude: -122.03074 },
87
+ { latitude: 34.145760590909, longitude: -118.15204363636 },
88
+ { latitude: 37.7815, longitude: -122.404933 }
89
+ ]
90
+
91
+ addresses = geocodio.reverse_geocode(*coordinate_pairs)
92
+
93
+ expect(addresses.size).to eq(3)
94
+ addresses.each { |address| expect(address).to be_a(Geocodio::AddressSet) }
95
+ end
96
+ end
97
+
98
+ it 'uses an arbitrary combination of strings and hashes' do
99
+ VCR.use_cassette('batch_reverse') do
100
+ coordinate_pairs = [
101
+ { latitude: 37.331669, longitude: -122.03074 },
102
+ '34.145760590909,-118.15204363636',
103
+ { latitude: 37.7815, longitude: -122.404933 }
104
+ ]
105
+
106
+ addresses = geocodio.reverse_geocode(*coordinate_pairs)
107
+
108
+ expect(addresses.size).to eq(3)
109
+ addresses.each { |address| expect(address).to be_a(Geocodio::AddressSet) }
110
+ end
111
+ end
112
+ end
44
113
  end
@@ -0,0 +1,53 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://api.geocod.io/v1/reverse?api_key=secret_api_key
6
+ body:
7
+ encoding: UTF-8
8
+ string: "[\"37.331669,-122.03074\",\"34.145760590909,-118.15204363636\",\"37.7815,-122.404933\"]"
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ User-Agent:
15
+ - Ruby
16
+ Content-Type:
17
+ - application/json
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Date:
24
+ - Mon, 03 Feb 2014 16:12:36 GMT
25
+ Server:
26
+ - Apache
27
+ X-Powered-By:
28
+ - PHP/5.4.24
29
+ Cache-Control:
30
+ - no-cache
31
+ Access-Control-Allow-Origin:
32
+ - "*"
33
+ Transfer-Encoding:
34
+ - chunked
35
+ Content-Type:
36
+ - application/json
37
+ body:
38
+ encoding: UTF-8
39
+ string: "{\"results\":[{\"query\":\"37.331669,-122.03074\",\"response\":{\"results\":[]}},{\"query\":\"34.145760590909,-118.15204363636\",\"response\":{\"results\":[{\"address_components\":{\"number\":\"43\",\"predirectional\":\"W\",\"street\":\"Colorado\",\"suffix\":\"Blvd\",\"city\":\"Pasadena\",\"state\":\"CA\",\"zip\":\"91105\"},\"formatted_address\":\"43
40
+ W Colorado Blvd, Pasadena, CA 91105\",\"location\":{\"lat\":34.145766,\"lng\":-118.15141},\"accuracy\":1},{\"address_components\":{\"number\":\"1\",\"predirectional\":\"N\",\"street\":\"De
41
+ Lacey\",\"suffix\":\"Ave\",\"city\":\"Pasadena\",\"state\":\"CA\",\"zip\":\"91103\"},\"formatted_address\":\"1
42
+ N De Lacey Ave, Pasadena, CA 91103\",\"location\":{\"lat\":34.145759,\"lng\":-118.15223},\"accuracy\":0},{\"address_components\":{\"number\":\"1\",\"predirectional\":\"S\",\"street\":\"De
43
+ Lacey\",\"suffix\":\"Ave\",\"city\":\"Pasadena\",\"state\":\"CA\",\"zip\":\"91105\"},\"formatted_address\":\"1
44
+ S De Lacey Ave, Pasadena, CA 91105\",\"location\":{\"lat\":34.145759,\"lng\":-118.15223},\"accuracy\":0}]}},{\"query\":\"37.7815,-122.404933\",\"response\":{\"results\":[{\"address_components\":{\"number\":\"177\",\"street\":\"5th\",\"suffix\":\"St\",\"city\":\"San
45
+ Francisco\",\"state\":\"CA\",\"zip\":\"94102\"},\"formatted_address\":\"177
46
+ 5th St, San Francisco, CA 94102\",\"location\":{\"lat\":37.781925,\"lng\":-122.405466},\"accuracy\":0},{\"address_components\":{\"number\":\"861\",\"street\":\"Howard\",\"suffix\":\"St\",\"city\":\"San
47
+ Francisco\",\"state\":\"CA\",\"zip\":\"94103\"},\"formatted_address\":\"861
48
+ Howard St, San Francisco, CA 94103\",\"location\":{\"lat\":37.782831,\"lng\":-122.40325},\"accuracy\":0},{\"address_components\":{\"number\":\"900\",\"street\":\"Howard\",\"suffix\":\"St\",\"city\":\"San
49
+ Francisco\",\"state\":\"CA\",\"zip\":\"94103\"},\"formatted_address\":\"900
50
+ Howard St, San Francisco, CA 94103\",\"location\":{\"lat\":37.7815,\"lng\":-122.404933},\"accuracy\":0}]}}]}"
51
+ http_version:
52
+ recorded_at: Mon, 03 Feb 2014 16:12:38 GMT
53
+ recorded_with: VCR 2.8.0
@@ -19,7 +19,7 @@ http_interactions:
19
19
  message: OK
20
20
  headers:
21
21
  Date:
22
- - Sun, 02 Feb 2014 17:40:52 GMT
22
+ - Mon, 03 Feb 2014 16:11:04 GMT
23
23
  Server:
24
24
  - Apache
25
25
  X-Powered-By:
@@ -39,5 +39,5 @@ http_interactions:
39
39
  W Colorado Blvd, Pasadena, CA 91105\",\"location\":{\"lat\":34.145760590909,\"lng\":-118.15204363636},\"accuracy\":1},{\"address_components\":{\"number\":\"54\",\"predirectional\":\"W\",\"street\":\"Colorado\",\"suffix\":\"Blvd\",\"city\":\"Pasadena\",\"state\":\"CA\",\"zip\":\"91105\"},\"formatted_address\":\"54
40
40
  W Colorado Blvd, Pasadena, CA 91105\",\"location\":{\"lat\":34.1457634625,\"lng\":-118.15170725},\"accuracy\":0.8}]}"
41
41
  http_version:
42
- recorded_at: Sun, 02 Feb 2014 17:40:53 GMT
42
+ recorded_at: Mon, 03 Feb 2014 16:11:05 GMT
43
43
  recorded_with: VCR 2.8.0
@@ -0,0 +1,45 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://api.geocod.io/v1/reverse?api_key=secret_api_key&q=34.145760590909,-118.15204363636
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Date:
22
+ - Mon, 03 Feb 2014 16:12:36 GMT
23
+ Server:
24
+ - Apache
25
+ X-Powered-By:
26
+ - PHP/5.4.24
27
+ Cache-Control:
28
+ - no-cache
29
+ Access-Control-Allow-Origin:
30
+ - "*"
31
+ Transfer-Encoding:
32
+ - chunked
33
+ Content-Type:
34
+ - application/json
35
+ body:
36
+ encoding: UTF-8
37
+ string: "{\"results\":[{\"address_components\":{\"number\":\"43\",\"predirectional\":\"W\",\"street\":\"Colorado\",\"suffix\":\"Blvd\",\"city\":\"Pasadena\",\"state\":\"CA\",\"zip\":\"91105\"},\"formatted_address\":\"43
38
+ W Colorado Blvd, Pasadena, CA 91105\",\"location\":{\"lat\":34.145766,\"lng\":-118.15141},\"accuracy\":1},{\"address_components\":{\"number\":\"1\",\"predirectional\":\"N\",\"street\":\"De
39
+ Lacey\",\"suffix\":\"Ave\",\"city\":\"Pasadena\",\"state\":\"CA\",\"zip\":\"91103\"},\"formatted_address\":\"1
40
+ N De Lacey Ave, Pasadena, CA 91103\",\"location\":{\"lat\":34.145759,\"lng\":-118.15223},\"accuracy\":0},{\"address_components\":{\"number\":\"1\",\"predirectional\":\"S\",\"street\":\"De
41
+ Lacey\",\"suffix\":\"Ave\",\"city\":\"Pasadena\",\"state\":\"CA\",\"zip\":\"91105\"},\"formatted_address\":\"1
42
+ S De Lacey Ave, Pasadena, CA 91105\",\"location\":{\"lat\":34.145759,\"lng\":-118.15223},\"accuracy\":0}]}"
43
+ http_version:
44
+ recorded_at: Mon, 03 Feb 2014 16:12:38 GMT
45
+ recorded_with: VCR 2.8.0
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geocodio
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Celis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-02 00:00:00.000000000 Z
11
+ date: 2014-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -95,15 +95,18 @@ files:
95
95
  - lib/geocodio/client.rb
96
96
  - lib/geocodio/client/error.rb
97
97
  - lib/geocodio/client/response.rb
98
+ - lib/geocodio/utils.rb
98
99
  - lib/geocodio/version.rb
99
100
  - spec/address_set_spec.rb
100
101
  - spec/address_spec.rb
101
102
  - spec/client_spec.rb
102
103
  - spec/spec_helper.rb
103
104
  - spec/vcr_cassettes/batch_geocode.yml
105
+ - spec/vcr_cassettes/batch_reverse.yml
104
106
  - spec/vcr_cassettes/geocode.yml
105
107
  - spec/vcr_cassettes/invalid_key.yml
106
108
  - spec/vcr_cassettes/parse.yml
109
+ - spec/vcr_cassettes/reverse.yml
107
110
  homepage: https://github.com/davidcelis/geocodio
108
111
  licenses:
109
112
  - MIT
@@ -134,6 +137,8 @@ test_files:
134
137
  - spec/client_spec.rb
135
138
  - spec/spec_helper.rb
136
139
  - spec/vcr_cassettes/batch_geocode.yml
140
+ - spec/vcr_cassettes/batch_reverse.yml
137
141
  - spec/vcr_cassettes/geocode.yml
138
142
  - spec/vcr_cassettes/invalid_key.yml
139
143
  - spec/vcr_cassettes/parse.yml
144
+ - spec/vcr_cassettes/reverse.yml