geocodio 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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