google_maps_geocoder 0.4.0.pre1 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/CONTRIBUTING.md +22 -0
- data/.github/ISSUE_TEMPLATE.md +17 -0
- data/.github/ISSUE_TEMPLATE/bug-report.md +23 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +16 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +9 -0
- data/.travis.yml +6 -2
- data/LICENSE.txt +2 -2
- data/README.md +48 -46
- data/google_maps_geocoder.gemspec +12 -9
- data/lib/google_maps_geocoder/google_maps_geocoder.rb +98 -55
- data/lib/google_maps_geocoder/version.rb +1 -1
- data/spec/lib/google_maps_geocoder_spec.rb +46 -57
- data/spec/spec_helper.rb +7 -2
- metadata +58 -28
- data/.ruby-version +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f46234243841130a16f88cfaa7e5e1f3cfa0a3b077872340a8f962247631550b
|
4
|
+
data.tar.gz: '08cc73decc514ca46cb109b91c5a530a6add7d5baeae8fb0a982cccc619f4dff'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1f39673ac4fb7cf61a6a3168a74cd5953040fdbd7334c65ba7891195e35f16134613d2caf20ccc6a9faee677f339648c3cec0c987f339b8f872f92e2668d5d1
|
7
|
+
data.tar.gz: df17491635d7a798f19ba4df1c338bc057506ed54c743f1e417936272dc313389e37d7a3297fa450716a81498bee1f943db7e67f659b245e42123961e36e504a
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# How to contribute
|
2
|
+
|
3
|
+
## **Did you find a bug?**
|
4
|
+
|
5
|
+
1. **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/ivanoblomov/google_maps_geocoder/issues).
|
6
|
+
|
7
|
+
2. If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/ivanoblomov/google_maps_geocoder/issues/new). Be sure to include:
|
8
|
+
1. a **title and clear description**
|
9
|
+
2. as much **relevant information** as possible
|
10
|
+
3. a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.
|
11
|
+
|
12
|
+
## **Did you write a patch that fixes a bug or adds a new feature?**
|
13
|
+
|
14
|
+
1. **Add specs** that either reproduces the bug or covers the new feature. In the former's case, *make sure it fails without the fix!*
|
15
|
+
|
16
|
+
2. **Confirm your last build passes** on [Travis CI](https://travis-ci.org/ivanoblomov/google_maps_geocoder/branches).
|
17
|
+
|
18
|
+
3. **Update the inline documentation.** Format it with [YARD](http://www.rubydoc.info/gems/yard/file/docs/GettingStarted.md). For example, see [`GoogleMapsGeocoder.new`](https://github.com/ivanoblomov/google_maps_geocoder/blob/github-templates/lib/google_maps_geocoder/google_maps_geocoder.rb#L43-L50).
|
19
|
+
|
20
|
+
4. [Open a pull request](https://github.com/ivanoblomov/google_maps_geocoder/compare) with the patch or feature. Follow the template's directions.
|
21
|
+
|
22
|
+
## Thanks for contributing!
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Description
|
2
|
+
|
3
|
+
Provide as much background as you need to get the implementer up to speed on the problem to be solved. This can also include screenshots and links to other issues or pull requests.
|
4
|
+
|
5
|
+
# Steps to Reproduce
|
6
|
+
|
7
|
+
Don't forget to point out the difference between what *should* happen and what *does* happen. Here's an example:
|
8
|
+
|
9
|
+
1. Try geocoding "1600 Pennsylvania Ave":
|
10
|
+
```ruby
|
11
|
+
white_house = GoogleMapsGeocoder.new('1600 Pennsylvania Ave')
|
12
|
+
```
|
13
|
+
2. The formatted address doesn't match the White House:
|
14
|
+
```ruby
|
15
|
+
white_house.formatted_address
|
16
|
+
=> "1600 Pennsylvania Ave, Charleston, WV 25302, USA"
|
17
|
+
```
|
@@ -0,0 +1,23 @@
|
|
1
|
+
---
|
2
|
+
name: Bug report
|
3
|
+
about: Create a report to help us improve
|
4
|
+
|
5
|
+
---
|
6
|
+
|
7
|
+
# Description
|
8
|
+
|
9
|
+
Provide as much background as you need to get the implementer up to speed on the problem to be solved. This can also include screenshots and links to other issues or pull requests.
|
10
|
+
|
11
|
+
# Steps to Reproduce
|
12
|
+
|
13
|
+
Don't forget to point out the difference between what *should* happen and what *does* happen. Here's an example:
|
14
|
+
|
15
|
+
1. Try geocoding "1600 Pennsylvania Ave":
|
16
|
+
```ruby
|
17
|
+
white_house = GoogleMapsGeocoder.new('1600 Pennsylvania Ave')
|
18
|
+
```
|
19
|
+
2. The formatted address doesn't match the White House:
|
20
|
+
```ruby
|
21
|
+
white_house.formatted_address
|
22
|
+
=> "1600 Pennsylvania Ave, Charleston, WV 25302, USA"
|
23
|
+
```
|
@@ -0,0 +1,16 @@
|
|
1
|
+
---
|
2
|
+
name: Feature request
|
3
|
+
about: Suggest an idea for this project
|
4
|
+
---
|
5
|
+
|
6
|
+
# Goal
|
7
|
+
Explain this issue's purpose. Focus on the problem that needs to be solved and *not* a particular solution. For example: "Make it easier for users to reset their passwords."
|
8
|
+
|
9
|
+
# Description
|
10
|
+
1. Provide as much background as you need to familiarize the implementer with the problem to be solved.
|
11
|
+
2. Include:
|
12
|
+
* screenshots
|
13
|
+
* links to other issues or pull requests
|
14
|
+
|
15
|
+
# Success Criteria
|
16
|
+
How would a stakeholder test whether the feature was completed successfully?
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Closes: #
|
2
|
+
|
3
|
+
# Goal
|
4
|
+
What problem does this pull request solve? This should be close to the goal of the issue this pull request addresses.
|
5
|
+
|
6
|
+
# Approach
|
7
|
+
1. Describe the approach you chose to solve the above problem.
|
8
|
+
2. This will help code reviewers get oriented quickly.
|
9
|
+
3. It will also document for future maintainers exactly what changed (and why) when this PR was merged.
|
data/.travis.yml
CHANGED
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2011 Roderick Monje
|
1
|
+
Copyright (c) 2011-2017 Roderick Monje
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
17
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,31 +1,38 @@
|
|
1
1
|
# GoogleMapsGeocoder
|
2
2
|
|
3
|
-
[![
|
3
|
+
[![Build Status](https://secure.travis-ci.org/ivanoblomov/google_maps_geocoder.svg)](http://travis-ci.org/ivanoblomov/google_maps_geocoder)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/ivanoblomov/google_maps_geocoder.png)](https://codeclimate.com/github/ivanoblomov/google_maps_geocoder)
|
5
|
-
[![Coverage Status](https://coveralls.io/repos/ivanoblomov/google_maps_geocoder/badge.svg?branch=master
|
6
|
-
[![
|
7
|
-
[![
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/github/ivanoblomov/google_maps_geocoder/badge.svg?branch=master)](https://coveralls.io/github/ivanoblomov/google_maps_geocoder?branch=master)
|
6
|
+
[![Inline docs](http://inch-ci.org/github/Ivanoblomov/google_maps_geocoder.svg?branch=master)](http://inch-ci.org/github/Ivanoblomov/google_maps_geocoder)
|
7
|
+
[![Gem Version](https://badge.fury.io/rb/google_maps_geocoder.svg)](http://badge.fury.io/rb/google_maps_geocoder)
|
8
|
+
[![security](https://hakiri.io/github/ivanoblomov/google_maps_geocoder/master.svg)](https://hakiri.io/github/ivanoblomov/google_maps_geocoder/master)
|
8
9
|
|
9
|
-
A simple
|
10
|
+
A simple Plain Old Ruby Object wrapper for geocoding with Google Maps.
|
10
11
|
|
11
12
|
## Installation
|
12
13
|
|
13
|
-
|
14
|
+
1. Set your Google Maps API key, which Google now requires, as an environment variable:
|
14
15
|
|
15
|
-
```
|
16
|
-
|
17
|
-
```
|
16
|
+
```bash
|
17
|
+
export GOOGLE_MAPS_API_KEY=[your key]
|
18
|
+
```
|
18
19
|
|
19
|
-
|
20
|
+
2. Add `GoogleMapsGeocoder` to your Gemfile and run `bundle`:
|
20
21
|
|
21
|
-
```ruby
|
22
|
-
|
23
|
-
```
|
22
|
+
```ruby
|
23
|
+
gem 'google_maps_geocoder'
|
24
|
+
```
|
25
|
+
|
26
|
+
Or try it out in `irb` with:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
require './lib/google_maps_geocoder/google_maps_geocoder'
|
30
|
+
```
|
24
31
|
|
25
32
|
## Ready to Go in One Step
|
26
33
|
|
27
34
|
```ruby
|
28
|
-
chez_barack = GoogleMapsGeocoder.new '1600 Pennsylvania
|
35
|
+
chez_barack = GoogleMapsGeocoder.new '1600 Pennsylvania DC'
|
29
36
|
```
|
30
37
|
|
31
38
|
## Usage
|
@@ -62,38 +69,33 @@ chez_barack.state_short_name
|
|
62
69
|
|
63
70
|
The complete, hopefully self-explanatory, API is:
|
64
71
|
|
65
|
-
* city
|
66
|
-
* country_long_name
|
67
|
-
* country_short_name
|
68
|
-
* county
|
69
|
-
* exact_match
|
70
|
-
* formatted_address
|
71
|
-
* formatted_street_address
|
72
|
-
* lat
|
73
|
-
* lng
|
74
|
-
* partial_match
|
75
|
-
* postal_code
|
76
|
-
* state_long_name
|
77
|
-
* state_short_name
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
* Fork the project
|
92
|
-
* Start a feature/bugfix branch
|
93
|
-
* Commit and push until you are happy with your contribution
|
94
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
95
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
72
|
+
* `GoogleMapsGeocoder#city`
|
73
|
+
* `GoogleMapsGeocoder#country_long_name`
|
74
|
+
* `GoogleMapsGeocoder#country_short_name`
|
75
|
+
* `GoogleMapsGeocoder#county`
|
76
|
+
* `GoogleMapsGeocoder#exact_match?`
|
77
|
+
* `GoogleMapsGeocoder#formatted_address`
|
78
|
+
* `GoogleMapsGeocoder#formatted_street_address`
|
79
|
+
* `GoogleMapsGeocoder#lat`
|
80
|
+
* `GoogleMapsGeocoder#lng`
|
81
|
+
* `GoogleMapsGeocoder#partial_match?`
|
82
|
+
* `GoogleMapsGeocoder#postal_code`
|
83
|
+
* `GoogleMapsGeocoder#state_long_name`
|
84
|
+
* `GoogleMapsGeocoder#state_short_name`
|
85
|
+
|
86
|
+
For compatibility with [Geocoder](https://github.com/alexreisner/geocoder), the following aliases are also available:
|
87
|
+
|
88
|
+
* `GoogleMapsGeocoder#address`
|
89
|
+
* `GoogleMapsGeocoder#coordinates`
|
90
|
+
* `GoogleMapsGeocoder#country`
|
91
|
+
* `GoogleMapsGeocoder#country_code`
|
92
|
+
* `GoogleMapsGeocoder#latitude`
|
93
|
+
* `GoogleMapsGeocoder#longitude`
|
94
|
+
* `GoogleMapsGeocoder#state`
|
95
|
+
* `GoogleMapsGeocoder#state_code`
|
96
|
+
|
97
|
+
## [Contributing to GoogleMapsGeocoder](https://github.com/ivanoblomov/google_maps_geocoder/blob/master/.github/CONTRIBUTING.md)
|
96
98
|
|
97
99
|
## Copyright
|
98
100
|
|
99
|
-
Copyright
|
101
|
+
Copyright © 2011-2020 Roderick Monje. See [LICENSE.txt](https://github.com/ivanoblomov/google_maps_geocoder/blob/master/LICENSE.txt) for further details.
|
@@ -1,25 +1,28 @@
|
|
1
|
-
require File.expand_path
|
1
|
+
require File.expand_path('lib/google_maps_geocoder/version', __dir__)
|
2
2
|
Gem::Specification.new do |s|
|
3
3
|
s.name = 'google_maps_geocoder'
|
4
4
|
s.version = GoogleMapsGeocoder::VERSION.dup
|
5
|
+
s.licenses = ['MIT']
|
5
6
|
s.summary = 'A simple PORO wrapper for geocoding with Google Maps.'
|
6
7
|
s.description = 'Geocode a location without worrying about parsing Google '\
|
7
8
|
"Maps' response. GoogleMapsGeocoder wraps it in a plain-old "\
|
8
9
|
'Ruby object.'
|
9
|
-
s.homepage = '
|
10
|
+
s.homepage = 'https://github.com/ivanoblomov/google_maps_geocoder'
|
10
11
|
s.authors = ['Roderick Monje']
|
12
|
+
s.email = 'rod@foveacentral.com'
|
11
13
|
|
12
|
-
s.add_development_dependency '
|
13
|
-
s.add_development_dependency '
|
14
|
-
s.add_development_dependency '
|
15
|
-
s.add_development_dependency '
|
14
|
+
s.add_development_dependency 'codeclimate-test-reporter', '~> 0'
|
15
|
+
s.add_development_dependency 'coveralls', '~> 0'
|
16
|
+
s.add_development_dependency 'rake', '~> 12.3', '>= 12.3.3'
|
17
|
+
s.add_development_dependency 'rspec', '~> 3'
|
18
|
+
s.add_development_dependency 'rubocop', '~> 0.49.0'
|
16
19
|
|
17
|
-
s.add_runtime_dependency 'activesupport', '>=
|
18
|
-
s.add_runtime_dependency 'rack', '
|
20
|
+
s.add_runtime_dependency 'activesupport', '~> 4.1', '>= 4.1.11'
|
21
|
+
s.add_runtime_dependency 'rack', '~> 2.1.3'
|
19
22
|
|
20
23
|
s.files = `git ls-files`.split "\n"
|
21
24
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split "\n"
|
22
25
|
s.executables = `git ls-files -- bin/*`.split("\n")
|
23
|
-
|
26
|
+
.map { |f| File.basename f }
|
24
27
|
s.require_paths = ['lib']
|
25
28
|
end
|
@@ -4,79 +4,138 @@ require 'net/http'
|
|
4
4
|
require 'rack'
|
5
5
|
|
6
6
|
# A simple PORO wrapper for geocoding with Google Maps.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# chez_barack = GoogleMapsGeocoder.new '1600 Pennsylvania DC'
|
10
|
+
# chez_barack.formatted_address
|
11
|
+
# => "1600 Pennsylvania Avenue Northwest, President's Park,
|
12
|
+
# Washington, DC 20500, USA"
|
7
13
|
class GoogleMapsGeocoder
|
8
|
-
GOOGLE_ADDRESS_SEGMENTS = %i
|
14
|
+
GOOGLE_ADDRESS_SEGMENTS = %i[
|
9
15
|
city country_long_name country_short_name county lat lng postal_code
|
10
16
|
state_long_name state_short_name
|
11
|
-
|
12
|
-
|
17
|
+
].freeze
|
18
|
+
GOOGLE_MAPS_API = 'https://maps.googleapis.com/maps/api/geocode/json'.freeze
|
13
19
|
|
14
20
|
ALL_ADDRESS_SEGMENTS = (
|
15
|
-
GOOGLE_ADDRESS_SEGMENTS + %i
|
16
|
-
formatted_address formatted_street_address
|
17
|
-
)
|
21
|
+
GOOGLE_ADDRESS_SEGMENTS + %i[formatted_address formatted_street_address]
|
18
22
|
).freeze
|
19
23
|
|
20
24
|
# Returns the complete formatted address with standardized abbreviations.
|
25
|
+
#
|
26
|
+
# @return [String] the complete formatted address
|
27
|
+
# @example
|
28
|
+
# chez_barack.formatted_address
|
29
|
+
# => "1600 Pennsylvania Avenue Northwest, President's Park,
|
30
|
+
# Washington, DC 20500, USA"
|
21
31
|
attr_reader :formatted_address
|
32
|
+
|
22
33
|
# Returns the formatted street address with standardized abbreviations.
|
34
|
+
#
|
35
|
+
# @return [String] the formatted street address
|
36
|
+
# @example
|
37
|
+
# chez_barack.formatted_street_address
|
38
|
+
# => "1600 Pennsylvania Avenue Northwest"
|
23
39
|
attr_reader :formatted_street_address
|
24
40
|
# Self-explanatory
|
25
41
|
attr_reader(*GOOGLE_ADDRESS_SEGMENTS)
|
26
42
|
|
27
|
-
#
|
28
|
-
|
29
|
-
#
|
30
|
-
|
31
|
-
#
|
43
|
+
# Returns the formatted address as a comma-delimited string.
|
44
|
+
alias address formatted_address
|
45
|
+
# Returns the address' country as a full string.
|
46
|
+
alias country country_long_name
|
47
|
+
# Returns the address' country as an abbreviated string.
|
48
|
+
alias country_code country_short_name
|
49
|
+
# Returns the address' latitude as a float.
|
50
|
+
alias latitude lat
|
51
|
+
# Returns the address' longitude as a float.
|
52
|
+
alias longitude lng
|
53
|
+
# Returns the address' state as a full string.
|
54
|
+
alias state state_long_name
|
55
|
+
# Returns the address' state as an abbreviated string.
|
56
|
+
alias state_code state_short_name
|
57
|
+
|
58
|
+
# Geocodes the specified address and wraps the results in a GoogleMapsGeocoder
|
59
|
+
# object.
|
32
60
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
@json
|
43
|
-
|
44
|
-
"#{@json.inspect}" if @json.blank? || @json['status'] != 'OK'
|
61
|
+
# @param address [String] a geocodable address
|
62
|
+
# @return [GoogleMapsGeocoder] the Google Maps result for the specified
|
63
|
+
# address
|
64
|
+
# @example
|
65
|
+
# chez_barack = GoogleMapsGeocoder.new '1600 Pennsylvania DC'
|
66
|
+
def initialize(address)
|
67
|
+
@json = address.is_a?(String) ? google_maps_response(address) : address
|
68
|
+
status = @json && @json['status']
|
69
|
+
raise RuntimeError if status == 'OVER_QUERY_LIMIT'
|
70
|
+
raise GeocodingError, @json if @json.blank? || status != 'OK'
|
71
|
+
|
45
72
|
set_attributes_from_json
|
46
|
-
|
47
|
-
"Geocoded \"#{
|
73
|
+
Logger.new(STDERR).info('GoogleMapsGeocoder') do
|
74
|
+
"Geocoded \"#{address}\" => \"#{formatted_address}\""
|
48
75
|
end
|
49
76
|
end
|
50
77
|
|
51
|
-
#
|
78
|
+
# Returns the address' coordinates as an array of floats.
|
79
|
+
def coordinates
|
80
|
+
[lat, lng]
|
81
|
+
end
|
52
82
|
|
53
83
|
# Returns true if the address Google returns is an exact match.
|
54
84
|
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
# white_house.exact_match?
|
85
|
+
# @return [boolean] whether the Google Maps result is an exact match
|
86
|
+
# @example
|
87
|
+
# chez_barack.exact_match?
|
59
88
|
# => true
|
60
89
|
def exact_match?
|
61
|
-
!
|
90
|
+
!partial_match?
|
62
91
|
end
|
63
92
|
|
64
93
|
# Returns true if the address Google returns isn't an exact match.
|
65
94
|
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
# => false
|
95
|
+
# @return [boolean] whether the Google Maps result is a partial match
|
96
|
+
# @example
|
97
|
+
# GoogleMapsGeocoder.new('1600 Pennsylvania DC').partial_match?
|
98
|
+
# => true
|
71
99
|
def partial_match?
|
72
100
|
@json['results'][0]['partial_match'] == true
|
73
101
|
end
|
74
102
|
|
103
|
+
# A geocoding error returned by Google Maps.
|
104
|
+
class GeocodingError < StandardError
|
105
|
+
# Returns the complete JSON response from Google Maps as a Hash.
|
106
|
+
#
|
107
|
+
# @return [Hash] Google Maps' JSON response
|
108
|
+
# @example
|
109
|
+
# {
|
110
|
+
# "results" => [],
|
111
|
+
# "status" => "ZERO_RESULTS"
|
112
|
+
# }
|
113
|
+
attr_reader :json
|
114
|
+
|
115
|
+
# Initialize a GeocodingError wrapping the JSON returned by Google Maps.
|
116
|
+
#
|
117
|
+
# @param json [Hash] Google Maps' JSON response
|
118
|
+
# @return [GeocodingError] the geocoding error
|
119
|
+
def initialize(json = {})
|
120
|
+
@json = json
|
121
|
+
if (message = @json['error_message'])
|
122
|
+
Logger.new(STDERR).error(message)
|
123
|
+
end
|
124
|
+
super @json['status']
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
75
128
|
private
|
76
129
|
|
77
|
-
def
|
78
|
-
|
79
|
-
|
130
|
+
def google_maps_request(address)
|
131
|
+
"#{GOOGLE_MAPS_API}?address=#{Rack::Utils.escape address}"\
|
132
|
+
"&key=#{ENV['GOOGLE_MAPS_API_KEY']}"
|
133
|
+
end
|
134
|
+
|
135
|
+
def google_maps_response(address)
|
136
|
+
uri = URI.parse google_maps_request(address)
|
137
|
+
response = http(uri).request(Net::HTTP::Get.new(uri.request_uri))
|
138
|
+
ActiveSupport::JSON.decode response.body
|
80
139
|
end
|
81
140
|
|
82
141
|
def http(uri)
|
@@ -86,17 +145,6 @@ class GoogleMapsGeocoder
|
|
86
145
|
http
|
87
146
|
end
|
88
147
|
|
89
|
-
def json_from_url(url)
|
90
|
-
uri = URI.parse query_url(url)
|
91
|
-
logger.debug('GoogleMapsGeocoder') { uri }
|
92
|
-
response = http(uri).request(Net::HTTP::Get.new(uri.request_uri))
|
93
|
-
ActiveSupport::JSON.decode response.body
|
94
|
-
end
|
95
|
-
|
96
|
-
def logger
|
97
|
-
@logger ||= Logger.new STDERR
|
98
|
-
end
|
99
|
-
|
100
148
|
def parse_address_component_type(type, name = 'long_name')
|
101
149
|
address_component = @json['results'][0]['address_components'].detect do |ac|
|
102
150
|
ac['types'] && ac['types'].include?(type)
|
@@ -150,11 +198,6 @@ class GoogleMapsGeocoder
|
|
150
198
|
parse_address_component_type('administrative_area_level_1', 'short_name')
|
151
199
|
end
|
152
200
|
|
153
|
-
def query_url(query)
|
154
|
-
"#{GOOGLE_API_URI}?address=#{Rack::Utils.escape query}&sensor=false"\
|
155
|
-
"#{api_key}"
|
156
|
-
end
|
157
|
-
|
158
201
|
def set_attributes_from_json
|
159
202
|
ALL_ADDRESS_SEGMENTS.each do |segment|
|
160
203
|
instance_variable_set :"@#{segment}", send("parse_#{segment}")
|
@@ -1,10 +1,9 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
|
2
|
+
# rubocop:disable Metrics/BlockLength
|
3
3
|
describe GoogleMapsGeocoder do
|
4
4
|
before(:all) do
|
5
5
|
begin
|
6
|
-
@exact_match
|
7
|
-
@partial_match = GoogleMapsGeocoder.new('1600 Pennsylvania Washington')
|
6
|
+
@exact_match = GoogleMapsGeocoder.new('White House')
|
8
7
|
rescue SocketError
|
9
8
|
@no_network = true
|
10
9
|
rescue RuntimeError
|
@@ -17,68 +16,58 @@ describe GoogleMapsGeocoder do
|
|
17
16
|
pending 'waiting for query limit to pass' if @query_limit
|
18
17
|
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
describe '#new' do
|
20
|
+
context 'with "White House"' do
|
21
|
+
subject { @exact_match }
|
23
22
|
|
24
|
-
|
25
|
-
it { expect(subject.formatted_street_address).to eq '837 Union Street' }
|
26
|
-
it { expect(subject.city).to eq 'Brooklyn' }
|
27
|
-
it { expect(subject.county).to match(/Kings/) }
|
28
|
-
it { expect(subject.state_long_name).to eq 'New York' }
|
29
|
-
it { expect(subject.state_short_name).to eq 'NY' }
|
30
|
-
it { expect(subject.postal_code).to match(/112[0-9]{2}/) }
|
31
|
-
it { expect(subject.country_short_name).to eq 'US' }
|
32
|
-
it { expect(subject.country_long_name).to eq 'United States' }
|
33
|
-
it do
|
34
|
-
expect(subject.formatted_address)
|
35
|
-
.to match(/837 Union St, Brooklyn, NY 112[0-9]{2}, USA/)
|
36
|
-
end
|
37
|
-
end
|
23
|
+
it { should be_exact_match }
|
38
24
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
25
|
+
context 'address' do
|
26
|
+
it do
|
27
|
+
expect(subject.formatted_street_address)
|
28
|
+
.to eq '1600 Pennsylvania Avenue Northwest'
|
29
|
+
end
|
30
|
+
it { expect(subject.city).to eq 'Washington' }
|
31
|
+
it { expect(subject.state_long_name).to eq 'District of Columbia' }
|
32
|
+
it { expect(subject.state_short_name).to eq 'DC' }
|
33
|
+
it { expect(subject.postal_code).to eq '20500' }
|
34
|
+
it { expect(subject.country_short_name).to eq 'US' }
|
35
|
+
it { expect(subject.country_long_name).to eq 'United States' }
|
36
|
+
it do
|
37
|
+
expect(subject.formatted_address)
|
38
|
+
.to match(/1600 Pennsylvania Ave NW, Washington, DC 20500, USA/)
|
39
|
+
end
|
53
40
|
end
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
expect(subject.
|
62
|
-
|
41
|
+
context 'coordinates' do
|
42
|
+
it { expect(subject.lat).to be_within(0.005).of(38.8976633) }
|
43
|
+
it { expect(subject.lng).to be_within(0.005).of(-77.0365739) }
|
44
|
+
end
|
45
|
+
context 'Geocoder API' do
|
46
|
+
it { expect(subject.address).to eq subject.formatted_address }
|
47
|
+
it { expect(subject.coordinates).to eq [subject.lat, subject.lng] }
|
48
|
+
it { expect(subject.country).to eq subject.country_long_name }
|
49
|
+
it { expect(subject.country_code).to eq subject.country_short_name }
|
50
|
+
it { expect(subject.latitude).to eq subject.lat }
|
51
|
+
it { expect(subject.longitude).to eq subject.lng }
|
52
|
+
it { expect(subject.state).to eq subject.state_long_name }
|
53
|
+
it { expect(subject.state_code).to eq subject.state_short_name }
|
63
54
|
end
|
64
55
|
end
|
56
|
+
context 'when API key is invalid' do
|
57
|
+
before do
|
58
|
+
@key = ENV['GOOGLE_MAPS_API_KEY']
|
59
|
+
ENV['GOOGLE_MAPS_API_KEY'] = 'invalid_key'
|
60
|
+
end
|
65
61
|
|
66
|
-
|
67
|
-
it { expect(subject.lat).to be_within(0.005).of(38.8791981) }
|
68
|
-
it { expect(subject.lng).to be_within(0.005).of(-76.9818437) }
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context "when ENV['GOOGLE_MAPS_API_KEY'] = 'INVALID_KEY'" do
|
73
|
-
before { ENV['GOOGLE_MAPS_API_KEY'] = 'INVALID_KEY' }
|
62
|
+
after { ENV['GOOGLE_MAPS_API_KEY'] = @key }
|
74
63
|
|
75
|
-
|
64
|
+
subject { GoogleMapsGeocoder.new('nowhere that comes to mind') }
|
76
65
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
)
|
66
|
+
it do
|
67
|
+
expect { subject }.to raise_error GoogleMapsGeocoder::GeocodingError,
|
68
|
+
'REQUEST_DENIED'
|
69
|
+
end
|
82
70
|
end
|
83
71
|
end
|
84
72
|
end
|
73
|
+
# rubocop:enable Metrics/BlockLength
|
data/spec/spec_helper.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
1
3
|
require 'coveralls'
|
2
4
|
Coveralls.wear!
|
5
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
6
|
+
Coveralls::SimpleCov::Formatter
|
7
|
+
)
|
3
8
|
require 'rubygems'
|
4
9
|
require 'bundler'
|
5
10
|
begin
|
6
11
|
Bundler.setup(:default, :development)
|
7
12
|
rescue Bundler::BundlerError => e
|
8
|
-
|
9
|
-
|
13
|
+
warn e.message
|
14
|
+
warn 'Run `bundle install` to install missing gems'
|
10
15
|
exit e.status_code
|
11
16
|
end
|
12
17
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
metadata
CHANGED
@@ -1,109 +1,139 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google_maps_geocoder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roderick Monje
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-05-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: codeclimate-test-reporter
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: coveralls
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
|
-
- - "
|
31
|
+
- - "~>"
|
18
32
|
- !ruby/object:Gem::Version
|
19
33
|
version: '0'
|
20
34
|
type: :development
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
|
-
- - "
|
38
|
+
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '12.3'
|
31
48
|
- - ">="
|
32
49
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
50
|
+
version: 12.3.3
|
34
51
|
type: :development
|
35
52
|
prerelease: false
|
36
53
|
version_requirements: !ruby/object:Gem::Requirement
|
37
54
|
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '12.3'
|
38
58
|
- - ">="
|
39
59
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
60
|
+
version: 12.3.3
|
41
61
|
- !ruby/object:Gem::Dependency
|
42
62
|
name: rspec
|
43
63
|
requirement: !ruby/object:Gem::Requirement
|
44
64
|
requirements:
|
45
|
-
- - "
|
65
|
+
- - "~>"
|
46
66
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
67
|
+
version: '3'
|
48
68
|
type: :development
|
49
69
|
prerelease: false
|
50
70
|
version_requirements: !ruby/object:Gem::Requirement
|
51
71
|
requirements:
|
52
|
-
- - "
|
72
|
+
- - "~>"
|
53
73
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
74
|
+
version: '3'
|
55
75
|
- !ruby/object:Gem::Dependency
|
56
76
|
name: rubocop
|
57
77
|
requirement: !ruby/object:Gem::Requirement
|
58
78
|
requirements:
|
59
|
-
- - "
|
79
|
+
- - "~>"
|
60
80
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
81
|
+
version: 0.49.0
|
62
82
|
type: :development
|
63
83
|
prerelease: false
|
64
84
|
version_requirements: !ruby/object:Gem::Requirement
|
65
85
|
requirements:
|
66
|
-
- - "
|
86
|
+
- - "~>"
|
67
87
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
88
|
+
version: 0.49.0
|
69
89
|
- !ruby/object:Gem::Dependency
|
70
90
|
name: activesupport
|
71
91
|
requirement: !ruby/object:Gem::Requirement
|
72
92
|
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '4.1'
|
73
96
|
- - ">="
|
74
97
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
98
|
+
version: 4.1.11
|
76
99
|
type: :runtime
|
77
100
|
prerelease: false
|
78
101
|
version_requirements: !ruby/object:Gem::Requirement
|
79
102
|
requirements:
|
103
|
+
- - "~>"
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '4.1'
|
80
106
|
- - ">="
|
81
107
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
108
|
+
version: 4.1.11
|
83
109
|
- !ruby/object:Gem::Dependency
|
84
110
|
name: rack
|
85
111
|
requirement: !ruby/object:Gem::Requirement
|
86
112
|
requirements:
|
87
|
-
- - "
|
113
|
+
- - "~>"
|
88
114
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
115
|
+
version: 2.1.3
|
90
116
|
type: :runtime
|
91
117
|
prerelease: false
|
92
118
|
version_requirements: !ruby/object:Gem::Requirement
|
93
119
|
requirements:
|
94
|
-
- - "
|
120
|
+
- - "~>"
|
95
121
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
122
|
+
version: 2.1.3
|
97
123
|
description: Geocode a location without worrying about parsing Google Maps' response.
|
98
124
|
GoogleMapsGeocoder wraps it in a plain-old Ruby object.
|
99
|
-
email:
|
125
|
+
email: rod@foveacentral.com
|
100
126
|
executables: []
|
101
127
|
extensions: []
|
102
128
|
extra_rdoc_files: []
|
103
129
|
files:
|
104
130
|
- ".document"
|
131
|
+
- ".github/CONTRIBUTING.md"
|
132
|
+
- ".github/ISSUE_TEMPLATE.md"
|
133
|
+
- ".github/ISSUE_TEMPLATE/bug-report.md"
|
134
|
+
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
135
|
+
- ".github/PULL_REQUEST_TEMPLATE.md"
|
105
136
|
- ".gitignore"
|
106
|
-
- ".ruby-version"
|
107
137
|
- ".travis.yml"
|
108
138
|
- Gemfile
|
109
139
|
- LICENSE.txt
|
@@ -114,8 +144,9 @@ files:
|
|
114
144
|
- lib/google_maps_geocoder/version.rb
|
115
145
|
- spec/lib/google_maps_geocoder_spec.rb
|
116
146
|
- spec/spec_helper.rb
|
117
|
-
homepage:
|
118
|
-
licenses:
|
147
|
+
homepage: https://github.com/ivanoblomov/google_maps_geocoder
|
148
|
+
licenses:
|
149
|
+
- MIT
|
119
150
|
metadata: {}
|
120
151
|
post_install_message:
|
121
152
|
rdoc_options: []
|
@@ -128,12 +159,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
128
159
|
version: '0'
|
129
160
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
161
|
requirements:
|
131
|
-
- - "
|
162
|
+
- - ">="
|
132
163
|
- !ruby/object:Gem::Version
|
133
|
-
version:
|
164
|
+
version: '0'
|
134
165
|
requirements: []
|
135
|
-
|
136
|
-
rubygems_version: 2.4.6
|
166
|
+
rubygems_version: 3.1.2
|
137
167
|
signing_key:
|
138
168
|
specification_version: 4
|
139
169
|
summary: A simple PORO wrapper for geocoding with Google Maps.
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.2.2
|