google_maps_geocoder 0.4.0.pre1 → 0.5.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: 843c384bc9a07abcd15c8d310bced7b1fc80c979
4
- data.tar.gz: 3336c894ba548664bcfb7f5b2ef91aed785fff21
3
+ metadata.gz: 060caf858407bc718955028bc0edc35a518b2f63
4
+ data.tar.gz: 616a78c20c6ff0926380a413b51094fe8b824bf1
5
5
  SHA512:
6
- metadata.gz: fe1386c06d1bfedea6c5be18de70bd95455cda8778615f918d21bc7991ec197c5aee9bd8525bea23b520b8c00cd734c9a42aad68d5331277623eedb25569928f
7
- data.tar.gz: 105330f683835366620945bc14dd2b2118f9f3bc07a1d97f8445f5660152a919ec565c23196c1bf842b1c89ceb6f53e65f55af8f207780c7bcf7b8cdd1963fbd
6
+ metadata.gz: 6aebec357d9d33fbba4586cc7c09cceebcd3d159ecc7cd648b1548e6f80810838208f486fba1c526b81e73c40d30eb7e9cffed58912a8d1c1462aa6977d961a2
7
+ data.tar.gz: a624fd613c2c84ed5641186c1549135760d545976c4f83e12fce3c05322bdc24e7be9929e3f96020bc19f42608992af2de6d5035e23e070f6e9102bba9705017
data/README.md CHANGED
@@ -1,12 +1,13 @@
1
1
  # GoogleMapsGeocoder
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/google_maps_geocoder.svg)](http://badge.fury.io/rb/google_maps_geocoder)
3
+ [![Build Status](https://secure.travis-ci.org/ivanoblomov/google_maps_geocoder.png)](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
5
  [![Coverage Status](https://coveralls.io/repos/ivanoblomov/google_maps_geocoder/badge.svg?branch=master&service=github)](https://coveralls.io/github/ivanoblomov/google_maps_geocoder?branch=master)
6
- [![Build Status](https://secure.travis-ci.org/ivanoblomov/google_maps_geocoder.png)](http://travis-ci.org/ivanoblomov/google_maps_geocoder)
7
6
  [![Dependency Status](https://gemnasium.com/ivanoblomov/google_maps_geocoder.png)](https://gemnasium.com/ivanoblomov/google_maps_geocoder)
7
+ [![Inch CI](https://inch-ci.org/github/Ivanoblomov/google_maps_geocoder.svg?branch=master&style=flat)](https://inch-ci.org/github/Ivanoblomov/google_maps_geocoder)
8
+ [![Gem Version](https://badge.fury.io/rb/google_maps_geocoder.svg)](http://badge.fury.io/rb/google_maps_geocoder)
8
9
 
9
- A simple PORO wrapper for geocoding with Google Maps.
10
+ A simple Plain Old Ruby Object wrapper for geocoding with Google Maps.
10
11
 
11
12
  ## Installation
12
13
 
@@ -62,19 +63,19 @@ chez_barack.state_short_name
62
63
 
63
64
  The complete, hopefully self-explanatory, API is:
64
65
 
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
66
+ * `GoogleMapsGeocoder#city`
67
+ * `GoogleMapsGeocoder#country_long_name`
68
+ * `GoogleMapsGeocoder#country_short_name`
69
+ * `GoogleMapsGeocoder#county`
70
+ * `GoogleMapsGeocoder#exact_match?`
71
+ * `GoogleMapsGeocoder#formatted_address`
72
+ * `GoogleMapsGeocoder#formatted_street_address`
73
+ * `GoogleMapsGeocoder#lat`
74
+ * `GoogleMapsGeocoder#lng`
75
+ * `GoogleMapsGeocoder#partial_match?`
76
+ * `GoogleMapsGeocoder#postal_code`
77
+ * `GoogleMapsGeocoder#state_long_name`
78
+ * `GoogleMapsGeocoder#state_short_name`
78
79
 
79
80
  ## Google Maps API Key (Optional)
80
81
 
@@ -9,6 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.homepage = 'http://github.com/ivanoblomov/google_maps_geocoder'
10
10
  s.authors = ['Roderick Monje']
11
11
 
12
+ s.add_development_dependency 'codeclimate-test-reporter', '>= 0'
12
13
  s.add_development_dependency 'coveralls', '>= 0'
13
14
  s.add_development_dependency 'rake', '>= 0'
14
15
  s.add_development_dependency 'rspec', '>= 0'
@@ -20,6 +21,6 @@ Gem::Specification.new do |s|
20
21
  s.files = `git ls-files`.split "\n"
21
22
  s.test_files = `git ls-files -- {test,spec,features}/*`.split "\n"
22
23
  s.executables = `git ls-files -- bin/*`.split("\n")
23
- .map { |f| File.basename f }
24
+ .map { |f| File.basename f }
24
25
  s.require_paths = ['lib']
25
26
  end
@@ -1,10 +1,43 @@
1
1
  require 'active_support'
2
+ require 'active_support/core_ext/string/inflections'
2
3
  require 'logger'
3
4
  require 'net/http'
4
5
  require 'rack'
5
6
 
6
7
  # A simple PORO wrapper for geocoding with Google Maps.
8
+ #
9
+ # @example
10
+ # chez_barack = GoogleMapsGeocoder.new '1600 Pennsylvania Ave'
11
+ # chez_barack.formatted_address
12
+ # => "1600 Pennsylvania Avenue Northwest, President's Park,
13
+ # Washington, DC 20500, USA"
14
+ # rubocop:disable Metrics/ClassLength
7
15
  class GoogleMapsGeocoder
16
+ # Error handling for google statuses
17
+ class GeocodingError < StandardError
18
+ def initialize(response_json = '')
19
+ @json = response_json
20
+ super
21
+ end
22
+
23
+ def message
24
+ "Google returned:\n#{@json.inspect}"
25
+ end
26
+ end
27
+
28
+ class ZeroResultsError < GeocodingError; end
29
+ class QueryLimitError < GeocodingError; end
30
+ class RequestDeniedError < GeocodingError; end
31
+ class InvalidRequestError < GeocodingError; end
32
+ class UnknownError < GeocodingError; end
33
+
34
+ ERROR_STATUSES = { zero_results: 'ZERO_RESULTS',
35
+ query_limit: 'OVER_QUERY_LIMIT',
36
+ request_denied: 'REQUEST_DENIED',
37
+ invalid_request: 'INVALID_REQUEST',
38
+ unknown: 'UNKNOWN_ERROR'
39
+ }.freeze
40
+
8
41
  GOOGLE_ADDRESS_SEGMENTS = %i(
9
42
  city country_long_name country_short_name county lat lng postal_code
10
43
  state_long_name state_short_name
@@ -18,60 +51,65 @@ class GoogleMapsGeocoder
18
51
  ).freeze
19
52
 
20
53
  # Returns the complete formatted address with standardized abbreviations.
54
+ #
55
+ # @return [String] the complete formatted address
56
+ # @example
57
+ # chez_barack.formatted_address
58
+ # => "1600 Pennsylvania Avenue Northwest, President's Park,
59
+ # Washington, DC 20500, USA"
21
60
  attr_reader :formatted_address
61
+
22
62
  # Returns the formatted street address with standardized abbreviations.
63
+ #
64
+ # @return [String] the formatted street address
65
+ # @example
66
+ # chez_barack.formatted_street_address
67
+ # => "1600 Pennsylvania Avenue"
23
68
  attr_reader :formatted_street_address
24
69
  # Self-explanatory
25
70
  attr_reader(*GOOGLE_ADDRESS_SEGMENTS)
26
71
 
27
- # Instance Methods: Overrides ================================================
28
-
29
- # Geocodes the specified address and wraps the results in a geocoder object.
30
- #
31
- # ==== Attributes
32
- #
33
- # * +data+ - a geocodable address
72
+ # Geocodes the specified address and wraps the results in a GoogleMapsGeocoder
73
+ # object.
34
74
  #
35
- # ==== Examples
36
- #
37
- # white_house = GoogleMapsGeocoder.new('1600 Pennsylvania Washington')
38
- # white_house.formatted_address
39
- # => "1600 Pennsylvania Avenue Northwest, President's Park,
40
- # Washington, DC 20500, USA"
75
+ # @param data [String] a geocodable address
76
+ # @return [GoogleMapsGeocoder] the Google Maps result for the specified
77
+ # address
78
+ # @example
79
+ # chez_barack = GoogleMapsGeocoder.new '1600 Pennsylvania Ave'
41
80
  def initialize(data)
42
81
  @json = data.is_a?(String) ? json_from_url(data) : data
43
- fail "Geocoding \"#{data}\" exceeded query limit! Google returned...\n"\
44
- "#{@json.inspect}" if @json.blank? || @json['status'] != 'OK'
82
+ handle_error if @json.blank? || @json['status'] != 'OK'
45
83
  set_attributes_from_json
46
84
  logger.info('GoogleMapsGeocoder') do
47
85
  "Geocoded \"#{data}\" => \"#{formatted_address}\""
48
86
  end
49
87
  end
50
88
 
51
- # Instance Methods ===========================================================
52
-
53
89
  # Returns true if the address Google returns is an exact match.
54
90
  #
55
- # ==== Examples
56
- #
57
- # white_house = GoogleMapsGeocoder.new('1600 Pennsylvania Ave')
58
- # white_house.exact_match?
91
+ # @return [boolean] whether the Google Maps result is an exact match
92
+ # @example
93
+ # chez_barack.exact_match?
59
94
  # => true
60
95
  def exact_match?
61
- !self.partial_match?
96
+ !partial_match?
62
97
  end
63
98
 
64
99
  # Returns true if the address Google returns isn't an exact match.
65
100
  #
66
- # ==== Examples
67
- #
68
- # white_house = GoogleMapsGeocoder.new('1600 Pennsylvania Washington')
69
- # white_house.exact_match?
70
- # => false
101
+ # @return [boolean] whether the Google Maps result is a partial match
102
+ # @example
103
+ # GoogleMapsGeocoder.new('1600 Pennsylvania Washington').partial_match?
104
+ # => true
71
105
  def partial_match?
72
106
  @json['results'][0]['partial_match'] == true
73
107
  end
74
108
 
109
+ def self.error_class_name(key)
110
+ "google_maps_geocoder/#{key}_error".classify.constantize
111
+ end
112
+
75
113
  private
76
114
 
77
115
  def api_key
@@ -88,11 +126,23 @@ class GoogleMapsGeocoder
88
126
 
89
127
  def json_from_url(url)
90
128
  uri = URI.parse query_url(url)
129
+
91
130
  logger.debug('GoogleMapsGeocoder') { uri }
131
+
92
132
  response = http(uri).request(Net::HTTP::Get.new(uri.request_uri))
93
133
  ActiveSupport::JSON.decode response.body
94
134
  end
95
135
 
136
+ def handle_error
137
+ status = @json['status']
138
+ message = GeocodingError.new(@json).message
139
+
140
+ # for status codes see https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes
141
+ ERROR_STATUSES.each do |key, value|
142
+ raise GoogleMapsGeocoder.error_class_name(key), message if status == value
143
+ end
144
+ end
145
+
96
146
  def logger
97
147
  @logger ||= Logger.new STDERR
98
148
  end
@@ -1,4 +1,4 @@
1
1
  # A simple PORO wrapper for geocoding with Google Maps.
2
2
  class GoogleMapsGeocoder
3
- VERSION = '0.4.0.pre1'.freeze unless defined?(GoogleMapsGeocoder::VERSION)
3
+ VERSION = '0.5.0'.freeze unless defined?(GoogleMapsGeocoder::VERSION)
4
4
  end
@@ -75,10 +75,24 @@ describe GoogleMapsGeocoder do
75
75
  subject { @exact_match }
76
76
 
77
77
  it do
78
- expect(subject.send :query_url, nil).to eq(
78
+ expect(subject.send(:query_url, nil)).to eq(
79
79
  'https://maps.googleapis.com/maps/api/geocode/json?address='\
80
80
  '&sensor=false&key=INVALID_KEY'
81
81
  )
82
82
  end
83
83
  end
84
+
85
+ context 'with google returns empty results' do
86
+ let(:results_hash) { { 'results' => [] } }
87
+
88
+ GoogleMapsGeocoder::ERROR_STATUSES.each do |key, value|
89
+ it "raises #{key} error" do
90
+ allow_any_instance_of(GoogleMapsGeocoder).to receive(:json_from_url)\
91
+ .and_return results_hash.merge('status' => value)
92
+
93
+ expect { GoogleMapsGeocoder.new('anything') }.to \
94
+ raise_error(GoogleMapsGeocoder.error_class_name(key))
95
+ end
96
+ end
97
+ end
84
98
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,11 @@
1
+ require 'codeclimate-test-reporter'
2
+ CodeClimate::TestReporter.start
1
3
  require 'coveralls'
2
4
  Coveralls.wear!
5
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
6
+ CodeClimate::TestReporter::Formatter,
7
+ Coveralls::SimpleCov::Formatter
8
+ ]
3
9
  require 'rubygems'
4
10
  require 'bundler'
5
11
  begin
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google_maps_geocoder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.pre1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roderick Monje
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-28 00:00:00.000000000 Z
11
+ date: 2016-04-25 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
@@ -128,12 +142,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
128
142
  version: '0'
129
143
  required_rubygems_version: !ruby/object:Gem::Requirement
130
144
  requirements:
131
- - - ">"
145
+ - - ">="
132
146
  - !ruby/object:Gem::Version
133
- version: 1.3.1
147
+ version: '0'
134
148
  requirements: []
135
149
  rubyforge_project:
136
- rubygems_version: 2.4.6
150
+ rubygems_version: 2.4.5
137
151
  signing_key:
138
152
  specification_version: 4
139
153
  summary: A simple PORO wrapper for geocoding with Google Maps.