geokit-premier 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .loadpath
2
+ .project
3
+ pkg
4
+ .idea
5
+ .bundle
6
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ # source 'http://rubygems.org'
4
+ # source 'http://gemcutter.org'
5
+ # gem 'rspec-mocks', ">= 2.0.0.beta.23"
6
+ # gem "rspec-rails", ">= 2.0.0.beta.23"
7
+
8
+ # Specify your gem's dependencies in geokit-premier.gemspec
9
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,58 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ geokit-premier (0.0.5)
5
+ hoe
6
+ json_pure
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ ZenTest (4.4.2)
12
+ activemodel (3.0.3)
13
+ activesupport (= 3.0.3)
14
+ builder (~> 2.1.2)
15
+ i18n (~> 0.4)
16
+ activerecord (3.0.3)
17
+ activemodel (= 3.0.3)
18
+ activesupport (= 3.0.3)
19
+ arel (~> 2.0.2)
20
+ tzinfo (~> 0.3.23)
21
+ activesupport (3.0.3)
22
+ arel (2.0.7)
23
+ autotest (4.4.2)
24
+ builder (2.1.2)
25
+ diff-lcs (1.1.2)
26
+ hoe (2.8.0)
27
+ rake (>= 0.8.7)
28
+ i18n (0.5.0)
29
+ json_pure (1.4.6)
30
+ mysql (2.8.1)
31
+ rake (0.8.7)
32
+ rspec (2.0.1)
33
+ rspec-core (~> 2.0.1)
34
+ rspec-expectations (~> 2.0.1)
35
+ rspec-mocks (~> 2.0.1)
36
+ rspec-core (2.0.1)
37
+ rspec-expectations (2.0.1)
38
+ diff-lcs (>= 1.1.2)
39
+ rspec-mocks (2.0.1)
40
+ rspec-core (~> 2.0.1)
41
+ rspec-expectations (~> 2.0.1)
42
+ standalone_migrations (0.3.0)
43
+ activerecord
44
+ rake
45
+ tzinfo (0.3.24)
46
+
47
+ PLATFORMS
48
+ ruby
49
+
50
+ DEPENDENCIES
51
+ ZenTest
52
+ autotest
53
+ geokit-premier!
54
+ hoe
55
+ json_pure
56
+ mysql
57
+ rspec
58
+ standalone_migrations
data/History.txt ADDED
@@ -0,0 +1,77 @@
1
+ === 1.5.0 / 2009-09-21
2
+ * fixed jruby compatibility (thanks manalang)
3
+ * added country name to Google reverse geocoder (thanks joahking)
4
+ * added DependentLocalityName as district, and SubAdministrativeAreaName as province (google geocoder only)
5
+ * Google geocoder throws an error if you exceed geocoding rates (thanks drogus)
6
+
7
+ === 1.4.1 / 2009-06-15
8
+ * Fixed Ruby 1.9.1 compat and load order (thanks Niels Ganser)
9
+
10
+ === 1.4.0 / 2009-05-27
11
+ * Added country code/viewport biasing to GoogleGeocoder. Added Bounds#to_span method
12
+ * Added suggested_bounds (Geokit::Bounds) property to GeoLoc. (Google geocoder only)
13
+ * Added LatLng#reverse_geocode convenience method (thanks Tisho Georgiev for all three)
14
+
15
+ === 1.3.2 / 2009-05-27
16
+ * Fixed blank address geocoding bug
17
+
18
+ === 1.3.1 / 2009-05-21
19
+ * Support for External geocoders file (thanks dreamcat4)
20
+ * Support multiple ip geocoders, including new setting for ip_provider_order (thanks dreamcat4)
21
+
22
+ === 1.3.0 / 2009-04-11
23
+ * Added capability to define multiple API keys for different domains that may be pointing to the same application (thanks Glenn Powell)
24
+ * Added numeric accuracy accessor for Yahoo and Google geocoders (thanks Andrew Fecheyr Lippens)
25
+ * Implement #hash and #eql? on LatLng to allow for using it as a hash key (thanks Luke Melia and Ross Kaffenberger)
26
+ *
27
+
28
+ === 1.2.6 / 2009-03-19
29
+ * misc minor fixes
30
+
31
+ === 1.2.5 / 2009-02-25
32
+
33
+ * fixed GeoLoc.to_yaml
34
+ * fixed minor google geocoding bug
35
+ * now periodically publishing the Geokit gem to Rubyforge. Still maintaining development and managing contributions at Github
36
+
37
+ === 1.2.4 / 2009-02-25
38
+
39
+ * Improved Google geocoder in the Gem: Support for multiple geocoding results from the Google geocoder. (thanks github/pic)
40
+
41
+ === 1.2.3 / 2009-02-01
42
+
43
+ * Adding GeoPluginGeocoder for IP geocoding (thanks github/xjunior)
44
+ * Ruby 1.9.1 compatibility and Unicode fixes (thanks github/Nielsomat)
45
+ * various bug fixes
46
+
47
+ === 1.2.1 / 2009-01-05
48
+
49
+ * minor bug fixes
50
+ * reverse geocoding added (Google only): res=Geokit::Geocoders::GoogleGeocoder.reverse_geocode "37.791821,-122.394679"
51
+ * nautical miles added (in addition to miles and KM)
52
+
53
+ === 1.2.0 / 2008-12-01
54
+
55
+ * Improved Geocoder.us support -- respects authentication, and can geocode city names or zipcodes alone
56
+ * cross-meridian finds work correctly with bounds conditions
57
+ * fixed a problem with columns with "distance" in their name
58
+ * added Geonames geocoder
59
+ * the gem and plugin are now hosted at Github.
60
+
61
+ === 1.1.1 / 2008-01-20
62
+ * fixes for distance calculation (in-memory and database) when distances are either very small or 0.
63
+ * NOTE: older versions of MySQL/Postgres may not work. See readme for more info.
64
+
65
+ === 1.1.0 / 2007-12-07
66
+ * Geokit is now Rails 2.0 / Edge friendly.
67
+
68
+ === 1.0.0 / 2007-07-22
69
+ * see http://earthcode.com/blog/2007/07/new_geokit_release.html
70
+ * auto geocoding: an option to automatically geocode a model's address field on create
71
+ * in-memory sort-by-distance for arrays of location objects
72
+ * bounding box queries: `Location.find :all, :bounds=>[sw,ne]`
73
+ * improved performance by automatically adding a bounding box condition to radial queries
74
+ * new Bounds class for in-memory bounds-related operations
75
+ * ability to calculate heading and midpoint between two points
76
+ * ability to calculate endpoint given a point, heading, and distance
77
+
data/Rakefile CHANGED
@@ -1,21 +1,2 @@
1
- # -*- ruby -*-
2
-
3
- require 'rubygems'
4
- require 'hoe'
5
- require './lib/geokit.rb'
6
-
7
- # undefined method `empty?' for nil:NilClass
8
- # /Library/Ruby/Site/1.8/rubygems/specification.rb:886:in `validate'
9
- class NilClass
10
- def empty?
11
- true
12
- end
13
- end
14
-
15
- project=Hoe.new('geokit-premier', Geokit::VERSION) do |p|
16
- p.developer('Andrew Forward', 'aforward@gmail.com')
17
- p.summary="Fork of Geokit to provide for Google Premier users"
18
- end
19
-
20
-
21
- # vim: syntax=Ruby
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,2 @@
1
+ #Autotest.add_discovery { "rails" }
2
+ Autotest.add_discovery { "rspec2" }
Binary file
@@ -0,0 +1,54 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "geokit/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "geokit-premier"
7
+ s.version = Geokit::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Andrew Forward (forked project from Andre Lewis and Bill Eisenhauer)"]
10
+ s.email = ["aforward@gmail.com"]
11
+ s.homepage = "https://github.com/aforward/geokit-premier-gem"
12
+ s.summary = %q{Enables google geocoding using a premier account}
13
+ s.description = %q{Enhanced the google geocoder to take advantage of the premier account offering}
14
+
15
+ s.add_dependency('json_pure')
16
+ s.add_dependency('hoe')
17
+
18
+ s.add_development_dependency('rspec')
19
+ s.add_development_dependency('autotest')
20
+ s.add_development_dependency('ZenTest')
21
+ s.add_development_dependency('standalone_migrations')
22
+ s.add_development_dependency('mysql')
23
+
24
+ s.files = `git ls-files`.split("\n")
25
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
26
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
27
+ s.require_paths = ["lib"]
28
+ end
29
+
30
+ # -*- encoding: utf-8 -*-
31
+ # Gem::Specification.new do |s|
32
+ # # s.name = %q{geokit-premier}
33
+ # s.version = "0.0.4"
34
+ #
35
+ # # s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
36
+ # # s.date = %q{2009-08-02}
37
+ # # s.extra_rdoc_files = ["Manifest.txt", "README.markdown"]
38
+ # # s.files = ["Manifest.txt", "README.markdown", "Rakefile", "lib/geokit/geocoders.rb", "lib/geokit.rb", "lib/geokit/mappable.rb", "spec/geocoder_spec.rb", "spec/spec_helper.rb", "test/test_base_geocoder.rb", "test/test_bounds.rb", "test/test_ca_geocoder.rb", "test/test_geoloc.rb", "test/test_google_geocoder.rb", "test/test_latlng.rb", "test/test_multi_geocoder.rb", "test/test_us_geocoder.rb", "test/test_yahoo_geocoder.rb"]
39
+ # # s.has_rdoc = true
40
+ # # s.rdoc_options = ["--main", "README.markdown"]
41
+ # # s.rubygems_version = %q{1.3.5}
42
+ # # s.summary = %q{none}
43
+ # # s.test_files = ["spec/geocoder_spec.rb", "test/test_base_geocoder.rb", "test/test_bounds.rb", "test/test_ca_geocoder.rb", "test/test_geoloc.rb",
44
+ # # "test/test_geoplugin_geocoder.rb", "test/test_google_geocoder.rb", "test/test_google_reverse_geocoder.rb",
45
+ # # "test/test_inflector.rb", "test/test_ipgeocoder.rb", "test/test_latlng.rb", "test/test_multi_geocoder.rb",
46
+ # # "test/test_multi_ip_geocoder.rb", "test/test_us_geocoder.rb", "test/test_yahoo_geocoder.rb"]
47
+ #
48
+ # if s.respond_to? :specification_version then
49
+ # current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ # s.specification_version = 2
51
+ # end
52
+ # end
53
+
54
+
data/lib/geokit.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  module Geokit
2
- VERSION = '0.0.4'
3
2
  # These defaults are used in Geokit::Mappable.distance_to and in acts_as_mappable
4
3
  @@default_units = :miles
5
4
  @@default_formula = :sphere
@@ -0,0 +1,728 @@
1
+ require 'net/http'
2
+ require 'ipaddr'
3
+ require 'rexml/document'
4
+ require 'yaml'
5
+ require 'timeout'
6
+ require 'logger'
7
+ require 'base64'
8
+
9
+ module Geokit
10
+
11
+ class TooManyQueriesError < StandardError; end
12
+
13
+ module Inflector
14
+
15
+ extend self
16
+
17
+ def titleize(word)
18
+ humanize(underscore(word)).gsub(/\b([a-z])/u) { $1.capitalize }
19
+ end
20
+
21
+ def underscore(camel_cased_word)
22
+ camel_cased_word.to_s.gsub(/::/, '/').
23
+ gsub(/([A-Z]+)([A-Z][a-z])/u,'\1_\2').
24
+ gsub(/([a-z\d])([A-Z])/u,'\1_\2').
25
+ tr("-", "_").
26
+ downcase
27
+ end
28
+
29
+ def humanize(lower_case_and_underscored_word)
30
+ lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
31
+ end
32
+
33
+ def snake_case(s)
34
+ return s.downcase if s =~ /^[A-Z]+$/u
35
+ s.gsub(/([A-Z]+)(?=[A-Z][a-z]?)|\B[A-Z]/u, '_\&') =~ /_*(.*)/
36
+ return $+.downcase
37
+
38
+ end
39
+
40
+ def url_escape(s)
41
+ s.gsub(/([^ a-zA-Z0-9_.-]+)/nu) do
42
+ '%' + $1.unpack('H2' * $1.size).join('%').upcase
43
+ end.tr(' ', '+')
44
+ end
45
+
46
+ def camelize(str)
47
+ str.split('_').map {|w| w.capitalize}.join
48
+ end
49
+ end
50
+
51
+ # Contains a range of geocoders:
52
+ #
53
+ # ### "regular" address geocoders
54
+ # * Yahoo Geocoder - requires an API key.
55
+ # * Geocoder.us - may require authentication if performing more than the free request limit.
56
+ # * Geocoder.ca - for Canada; may require authentication as well.
57
+ # * Geonames - a free geocoder
58
+ #
59
+ # ### address geocoders that also provide reverse geocoding
60
+ # * Google Geocoder - requires an API key.
61
+ #
62
+ # ### IP address geocoders
63
+ # * IP Geocoder - geocodes an IP address using hostip.info's web service.
64
+ # * Geoplugin.net -- another IP address geocoder
65
+ #
66
+ # ### The Multigeocoder
67
+ # * Multi Geocoder - provides failover for the physical location geocoders.
68
+ #
69
+ # Some of these geocoders require configuration. You don't have to provide it here. See the README.
70
+ module Geocoders
71
+ @@proxy_addr = nil
72
+ @@proxy_port = nil
73
+ @@proxy_user = nil
74
+ @@proxy_pass = nil
75
+ @@request_timeout = nil
76
+ @@yahoo = 'REPLACE_WITH_YOUR_YAHOO_KEY'
77
+ @@google = 'REPLACE_WITH_YOUR_GOOGLE_KEY'
78
+ @@google_client_id = nil #only used for premier accounts
79
+ @@google_premier_secret_key = nil
80
+ @@geocoder_us = false
81
+ @@geocoder_ca = false
82
+ @@geonames = false
83
+ @@provider_order = [:google,:us]
84
+ @@ip_provider_order = [:geo_plugin,:ip]
85
+ @@logger=Logger.new(STDOUT)
86
+ @@logger.level=Logger::INFO
87
+ @@domain = nil
88
+
89
+ def self.__define_accessors
90
+ class_variables.each do |v|
91
+ sym = v.to_s.delete("@").to_sym
92
+ unless self.respond_to? sym
93
+ module_eval <<-EOS, __FILE__, __LINE__
94
+ def self.#{sym}
95
+ value = if defined?(#{sym.to_s.upcase})
96
+ #{sym.to_s.upcase}
97
+ else
98
+ @@#{sym}
99
+ end
100
+ if value.is_a?(Hash)
101
+ value = (self.domain.nil? ? nil : value[self.domain]) || value.values.first
102
+ end
103
+ value
104
+ end
105
+
106
+ def self.#{sym}=(obj)
107
+ @@#{sym} = obj
108
+ end
109
+ EOS
110
+ end
111
+ end
112
+ end
113
+
114
+ __define_accessors
115
+
116
+ # Error which is thrown in the event a geocoding error occurs.
117
+ class GeocodeError < StandardError; end
118
+
119
+ # -------------------------------------------------------------------------------------------
120
+ # Geocoder Base class -- every geocoder should inherit from this
121
+ # -------------------------------------------------------------------------------------------
122
+
123
+ # The Geocoder base class which defines the interface to be used by all
124
+ # other geocoders.
125
+ class Geocoder
126
+ # Main method which calls the do_geocode template method which subclasses
127
+ # are responsible for implementing. Returns a populated GeoLoc or an
128
+ # empty one with a failed success code.
129
+ def self.geocode(address, options = {})
130
+ res = do_geocode(address, options)
131
+ return res.nil? ? GeoLoc.new : res
132
+ end
133
+ # Main method which calls the do_reverse_geocode template method which subclasses
134
+ # are responsible for implementing. Returns a populated GeoLoc or an
135
+ # empty one with a failed success code.
136
+ def self.reverse_geocode(latlng)
137
+ res = do_reverse_geocode(latlng)
138
+ return res.success? ? res : GeoLoc.new
139
+ end
140
+
141
+ # Call the geocoder service using the timeout if configured.
142
+ def self.call_geocoder_service(url)
143
+ Timeout::timeout(Geokit::Geocoders::request_timeout) { return self.do_get(url) } if Geokit::Geocoders::request_timeout
144
+ return self.do_get(url)
145
+ rescue TimeoutError
146
+ return nil
147
+ end
148
+
149
+ # Not all geocoders can do reverse geocoding. So, unless the subclass explicitly overrides this method,
150
+ # a call to reverse_geocode will return an empty GeoLoc. If you happen to be using MultiGeocoder,
151
+ # this will cause it to failover to the next geocoder, which will hopefully be one which supports reverse geocoding.
152
+ def self.do_reverse_geocode(latlng)
153
+ return GeoLoc.new
154
+ end
155
+
156
+ # This will sign a raw url with a private key
157
+ def self.sign_url(raw_url,private_key)
158
+ uri = URI.parse(raw_url)
159
+ url_to_sign = uri.path + "?" + uri.query
160
+ decoded_key = Geocoder.urlsafe_decode64(private_key)
161
+
162
+ sha1_digest = OpenSSL::Digest::Digest.new('sha1')
163
+ signature = OpenSSL::HMAC.digest(sha1_digest,decoded_key,url_to_sign)
164
+ encoded_signature = Geocoder.urlsafe_encode64(signature)
165
+ signed_url = "#{uri.scheme}://#{uri.host}#{uri.path}?#{uri.query}&signature=#{encoded_signature}".strip!
166
+ signed_url
167
+ end
168
+
169
+ # This will provide url safe base64 decoding
170
+ def self.urlsafe_decode64(raw_text)
171
+ decoded_text = raw_text.gsub('-','+').gsub('_', '/')
172
+ decoded_text = Base64.decode64(decoded_text)
173
+ decoded_text
174
+ end
175
+
176
+ # This will provide url safe base64 encoding
177
+ def self.urlsafe_encode64(raw_text)
178
+ encoded_text = Base64.encode64(raw_text)
179
+ encoded_text = encoded_text.gsub('+','-').gsub('/', '_')
180
+ encoded_text
181
+ end
182
+
183
+
184
+ protected
185
+
186
+ def self.logger()
187
+ Geokit::Geocoders::logger
188
+ end
189
+
190
+ private
191
+
192
+ # Wraps the geocoder call around a proxy if necessary.
193
+ def self.do_get(url)
194
+ uri = URI.parse(url)
195
+ req = Net::HTTP::Get.new(url)
196
+ req.basic_auth(uri.user, uri.password) if uri.userinfo
197
+ res = Net::HTTP::Proxy(GeoKit::Geocoders::proxy_addr,
198
+ GeoKit::Geocoders::proxy_port,
199
+ GeoKit::Geocoders::proxy_user,
200
+ GeoKit::Geocoders::proxy_pass).start(uri.host, uri.port) { |http| http.get(uri.path + "?" + uri.query) }
201
+ return res
202
+ end
203
+
204
+ # Adds subclass' geocode method making it conveniently available through
205
+ # the base class.
206
+ def self.inherited(clazz)
207
+ class_name = clazz.name.split('::').last
208
+ src = <<-END_SRC
209
+ def self.#{Geokit::Inflector.underscore(class_name)}(address, options = {})
210
+ #{class_name}.geocode(address, options)
211
+ end
212
+ END_SRC
213
+ class_eval(src)
214
+ end
215
+ end
216
+
217
+ # -------------------------------------------------------------------------------------------
218
+ # "Regular" Address geocoders
219
+ # -------------------------------------------------------------------------------------------
220
+
221
+ # Geocoder CA geocoder implementation. Requires the Geokit::Geocoders::GEOCODER_CA variable to
222
+ # contain true or false based upon whether authentication is to occur. Conforms to the
223
+ # interface set by the Geocoder class.
224
+ #
225
+ # Returns a response like:
226
+ # <?xml version="1.0" encoding="UTF-8" ?>
227
+ # <geodata>
228
+ # <latt>49.243086</latt>
229
+ # <longt>-123.153684</longt>
230
+ # </geodata>
231
+ class CaGeocoder < Geocoder
232
+
233
+ private
234
+
235
+ # Template method which does the geocode lookup.
236
+ def self.do_geocode(address, options = {})
237
+ raise ArgumentError('Geocoder.ca requires a GeoLoc argument') unless address.is_a?(GeoLoc)
238
+ url = construct_request(address)
239
+ res = self.call_geocoder_service(url)
240
+ return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
241
+ xml = res.body
242
+ logger.debug "Geocoder.ca geocoding. Address: #{address}. Result: #{xml}"
243
+ # Parse the document.
244
+ doc = REXML::Document.new(xml)
245
+ address.lat = doc.elements['//latt'].text
246
+ address.lng = doc.elements['//longt'].text
247
+ address.success = true
248
+ return address
249
+ rescue
250
+ logger.error "Caught an error during Geocoder.ca geocoding call: "+$!
251
+ return GeoLoc.new
252
+ end
253
+
254
+ # Formats the request in the format acceptable by the CA geocoder.
255
+ def self.construct_request(location)
256
+ url = ""
257
+ url += add_ampersand(url) + "stno=#{location.street_number}" if location.street_address
258
+ url += add_ampersand(url) + "addresst=#{Geokit::Inflector::url_escape(location.street_name)}" if location.street_address
259
+ url += add_ampersand(url) + "city=#{Geokit::Inflector::url_escape(location.city)}" if location.city
260
+ url += add_ampersand(url) + "prov=#{location.state}" if location.state
261
+ url += add_ampersand(url) + "postal=#{location.zip}" if location.zip
262
+ url += add_ampersand(url) + "auth=#{Geokit::Geocoders::geocoder_ca}" if Geokit::Geocoders::geocoder_ca
263
+ url += add_ampersand(url) + "geoit=xml"
264
+ 'http://geocoder.ca/?' + url
265
+ end
266
+
267
+ def self.add_ampersand(url)
268
+ url && url.length > 0 ? "&" : ""
269
+ end
270
+ end
271
+
272
+ # Geocoder Us geocoder implementation. Requires the Geokit::Geocoders::GEOCODER_US variable to
273
+ # contain true or false based upon whether authentication is to occur. Conforms to the
274
+ # interface set by the Geocoder class.
275
+ class UsGeocoder < Geocoder
276
+
277
+ private
278
+ def self.do_geocode(address, options = {})
279
+ address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
280
+
281
+ query = (address_str =~ /^\d{5}(?:-\d{4})?$/ ? "zip" : "address") + "=#{Geokit::Inflector::url_escape(address_str)}"
282
+ url = if GeoKit::Geocoders::geocoder_us
283
+ "http://#{GeoKit::Geocoders::geocoder_us}@geocoder.us/member/service/csv/geocode"
284
+ else
285
+ "http://geocoder.us/service/csv/geocode"
286
+ end
287
+
288
+ url = "#{url}?#{query}"
289
+ res = self.call_geocoder_service(url)
290
+
291
+ return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
292
+ data = res.body
293
+ logger.debug "Geocoder.us geocoding. Address: #{address}. Result: #{data}"
294
+ array = data.chomp.split(',')
295
+
296
+ if array.length == 5
297
+ res=GeoLoc.new
298
+ res.lat,res.lng,res.city,res.state,res.zip=array
299
+ res.country_code='US'
300
+ res.success=true
301
+ return res
302
+ elsif array.length == 6
303
+ res=GeoLoc.new
304
+ res.lat,res.lng,res.street_address,res.city,res.state,res.zip=array
305
+ res.country_code='US'
306
+ res.success=true
307
+ return res
308
+ else
309
+ logger.info "geocoder.us was unable to geocode address: "+address
310
+ return GeoLoc.new
311
+ end
312
+ rescue
313
+ logger.error "Caught an error during geocoder.us geocoding call: "+$!
314
+ return GeoLoc.new
315
+
316
+ end
317
+ end
318
+
319
+ # Yahoo geocoder implementation. Requires the Geokit::Geocoders::YAHOO variable to
320
+ # contain a Yahoo API key. Conforms to the interface set by the Geocoder class.
321
+ class YahooGeocoder < Geocoder
322
+
323
+ private
324
+
325
+ # Template method which does the geocode lookup.
326
+ def self.do_geocode(address, options = {})
327
+ address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
328
+ url="http://api.local.yahoo.com/MapsService/V1/geocode?appid=#{Geokit::Geocoders::yahoo}&location=#{Geokit::Inflector::url_escape(address_str)}"
329
+ res = self.call_geocoder_service(url)
330
+ return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
331
+ xml = res.body
332
+ doc = REXML::Document.new(xml)
333
+ logger.debug "Yahoo geocoding. Address: #{address}. Result: #{xml}"
334
+
335
+ if doc.elements['//ResultSet']
336
+ res=GeoLoc.new
337
+
338
+ #basic
339
+ res.lat=doc.elements['//Latitude'].text
340
+ res.lng=doc.elements['//Longitude'].text
341
+ res.country_code=doc.elements['//Country'].text
342
+ res.provider='yahoo'
343
+
344
+ #extended - false if not available
345
+ res.city=doc.elements['//City'].text if doc.elements['//City'] && doc.elements['//City'].text != nil
346
+ res.state=doc.elements['//State'].text if doc.elements['//State'] && doc.elements['//State'].text != nil
347
+ res.zip=doc.elements['//Zip'].text if doc.elements['//Zip'] && doc.elements['//Zip'].text != nil
348
+ res.street_address=doc.elements['//Address'].text if doc.elements['//Address'] && doc.elements['//Address'].text != nil
349
+ res.precision=doc.elements['//Result'].attributes['precision'] if doc.elements['//Result']
350
+ # set the accuracy as google does (added by Andruby)
351
+ res.accuracy=%w{unknown country state state city zip zip+4 street address building}.index(res.precision)
352
+ res.success=true
353
+ return res
354
+ else
355
+ logger.info "Yahoo was unable to geocode address: "+address
356
+ return GeoLoc.new
357
+ end
358
+
359
+ rescue
360
+ logger.info "Caught an error during Yahoo geocoding call: "+$!
361
+ return GeoLoc.new
362
+ end
363
+ end
364
+
365
+ # Another geocoding web service
366
+ # http://www.geonames.org
367
+ class GeonamesGeocoder < Geocoder
368
+
369
+ private
370
+
371
+ # Template method which does the geocode lookup.
372
+ def self.do_geocode(address, options = {})
373
+ address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
374
+ # geonames need a space seperated search string
375
+ address_str.gsub!(/,/, " ")
376
+ params = "/postalCodeSearch?placename=#{Geokit::Inflector::url_escape(address_str)}&maxRows=10"
377
+
378
+ if(GeoKit::Geocoders::geonames)
379
+ url = "http://ws.geonames.net#{params}&username=#{GeoKit::Geocoders::geonames}"
380
+ else
381
+ url = "http://ws.geonames.org#{params}"
382
+ end
383
+
384
+ res = self.call_geocoder_service(url)
385
+
386
+ return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
387
+
388
+ xml=res.body
389
+ logger.debug "Geonames geocoding. Address: #{address}. Result: #{xml}"
390
+ doc=REXML::Document.new(xml)
391
+
392
+ if(doc.elements['//geonames/totalResultsCount'].text.to_i > 0)
393
+ res=GeoLoc.new
394
+
395
+ # only take the first result
396
+ res.lat=doc.elements['//code/lat'].text if doc.elements['//code/lat']
397
+ res.lng=doc.elements['//code/lng'].text if doc.elements['//code/lng']
398
+ res.country_code=doc.elements['//code/countryCode'].text if doc.elements['//code/countryCode']
399
+ res.provider='genomes'
400
+ res.city=doc.elements['//code/name'].text if doc.elements['//code/name']
401
+ res.state=doc.elements['//code/adminName1'].text if doc.elements['//code/adminName1']
402
+ res.zip=doc.elements['//code/postalcode'].text if doc.elements['//code/postalcode']
403
+ res.success=true
404
+ return res
405
+ else
406
+ logger.info "Geonames was unable to geocode address: "+address
407
+ return GeoLoc.new
408
+ end
409
+
410
+ rescue
411
+ logger.error "Caught an error during Geonames geocoding call: "+$!
412
+ end
413
+ end
414
+
415
+ # -------------------------------------------------------------------------------------------
416
+ # Address geocoders that also provide reverse geocoding
417
+ # -------------------------------------------------------------------------------------------
418
+
419
+ # Google geocoder implementation. Requires the Geokit::Geocoders::GOOGLE variable to
420
+ # contain a Google API key. Conforms to the interface set by the Geocoder class.
421
+ class GoogleGeocoder < Geocoder
422
+
423
+ private
424
+
425
+ # Template method which does the reverse-geocode lookup.
426
+ def self.do_reverse_geocode(latlng)
427
+ latlng=LatLng.normalize(latlng)
428
+ res = self.call_geocoder_service("http://maps.google.com/maps/geo?ll=#{Geokit::Inflector::url_escape(latlng.ll)}&output=xml&key=#{Geokit::Geocoders::google}&oe=utf-8")
429
+ # res = Net::HTTP.get_response(URI.parse("http://maps.google.com/maps/geo?ll=#{Geokit::Inflector::url_escape(address_str)}&output=xml&key=#{Geokit::Geocoders::google}&oe=utf-8"))
430
+ return GeoLoc.new unless (res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPOK))
431
+ xml = res.body
432
+ logger.debug "Google reverse-geocoding. LL: #{latlng}. Result: #{xml}"
433
+ return self.xml2GeoLoc(xml)
434
+ end
435
+
436
+ # Template method which does the geocode lookup.
437
+ #
438
+ # Supports viewport/country code biasing
439
+ #
440
+ # ==== OPTIONS
441
+ # * :bias - This option makes the Google Geocoder return results biased to a particular
442
+ # country or viewport. Country code biasing is achieved by passing the ccTLD
443
+ # ('uk' for .co.uk, for example) as a :bias value. For a list of ccTLD's,
444
+ # look here: http://en.wikipedia.org/wiki/CcTLD. By default, the geocoder
445
+ # will be biased to results within the US (ccTLD .com).
446
+ #
447
+ # If you'd like the Google Geocoder to prefer results within a given viewport,
448
+ # you can pass a Geokit::Bounds object as the :bias value.
449
+ #
450
+ # ==== EXAMPLES
451
+ # # By default, the geocoder will return Syracuse, NY
452
+ # Geokit::Geocoders::GoogleGeocoder.geocode('Syracuse').country_code # => 'US'
453
+ # # With country code biasing, it returns Syracuse in Sicily, Italy
454
+ # Geokit::Geocoders::GoogleGeocoder.geocode('Syracuse', :bias => :it).country_code # => 'IT'
455
+ #
456
+ # # By default, the geocoder will return Winnetka, IL
457
+ # Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka').state # => 'IL'
458
+ # # When biased to an bounding box around California, it will now return the Winnetka neighbourhood, CA
459
+ # bounds = Geokit::Bounds.normalize([34.074081, -118.694401], [34.321129, -118.399487])
460
+ # Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka', :bias => bounds).state # => 'CA'
461
+ def self.do_geocode(address, options = {})
462
+ res = self.call_geocoder_service(self.geocode_url(address,options))
463
+ return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
464
+ xml = res.body
465
+ logger.debug "Google geocoding. Address: #{address}. Result: #{xml}"
466
+ return self.xml2GeoLoc(xml, address)
467
+ end
468
+
469
+ # Determine the Google API url based on the google api key, or based on the client / private key for premier users
470
+ def self.geocode_url(address,options = {})
471
+ bias_str = options[:bias] ? construct_bias_string_from_options(options[:bias]) : ''
472
+ address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
473
+
474
+ if !Geokit::Geocoders::google_client_id.nil? && !Geokit::Geocoders::google_premier_secret_key.nil?
475
+ url = "http://maps.googleapis.com/maps/api/geocode/xml?address=#{Geokit::Inflector::url_escape(address_str)}&client=#{Geokit::Geocoders::google_client_id}&sensor=false&oe=utf-8"
476
+ Geokit::Geocoders::Geocoder.sign_url(url,Geokit::Geocoders::google_premier_secret_key)
477
+ else
478
+ "http://maps.google.com/maps/geo?q=#{Geokit::Inflector::url_escape(address_str)}&output=xml#{bias_str}&key=#{Geokit::Geocoders::google}&oe=utf-8"
479
+ end
480
+ end
481
+
482
+
483
+ def self.construct_bias_string_from_options(bias)
484
+ if bias.is_a?(String) or bias.is_a?(Symbol)
485
+ # country code biasing
486
+ "&gl=#{bias.to_s.downcase}"
487
+ elsif bias.is_a?(Bounds)
488
+ # viewport biasing
489
+ "&ll=#{bias.center.ll}&spn=#{bias.to_span.ll}"
490
+ end
491
+ end
492
+
493
+ def self.xml2GeoLoc(xml, address="")
494
+ doc=REXML::Document.new(xml)
495
+
496
+ if doc.elements['//kml/Response/Status/code'].text == '200'
497
+ geoloc = nil
498
+ # Google can return multiple results as //Placemark elements.
499
+ # iterate through each and extract each placemark as a geoloc
500
+ doc.each_element('//Placemark') do |e|
501
+ extracted_geoloc = extract_placemark(e) # g is now an instance of GeoLoc
502
+ if geoloc.nil?
503
+ # first time through, geoloc is still nil, so we make it the geoloc we just extracted
504
+ geoloc = extracted_geoloc
505
+ else
506
+ # second (and subsequent) iterations, we push additional
507
+ # geolocs onto "geoloc.all"
508
+ geoloc.all.push(extracted_geoloc)
509
+ end
510
+ end
511
+ return geoloc
512
+ elsif doc.elements['//kml/Response/Status/code'].text == '620'
513
+ raise Geokit::TooManyQueriesError
514
+ else
515
+ logger.info "Google was unable to geocode address: "+address
516
+ return GeoLoc.new
517
+ end
518
+
519
+ rescue Geokit::TooManyQueriesError
520
+ # re-raise because of other rescue
521
+ raise Geokit::TooManyQueriesError, "Google returned a 620 status, too many queries. The given key has gone over the requests limit in the 24 hour period or has submitted too many requests in too short a period of time. If you're sending multiple requests in parallel or in a tight loop, use a timer or pause in your code to make sure you don't send the requests too quickly."
522
+ rescue
523
+ logger.error "Caught an error during Google geocoding call: "+$!
524
+ return GeoLoc.new
525
+ end
526
+
527
+ # extracts a single geoloc from a //placemark element in the google results xml
528
+ def self.extract_placemark(doc)
529
+ res = GeoLoc.new
530
+ coordinates=doc.elements['.//coordinates'].text.to_s.split(',')
531
+
532
+ #basics
533
+ res.lat=coordinates[1]
534
+ res.lng=coordinates[0]
535
+ res.country_code=doc.elements['.//CountryNameCode'].text if doc.elements['.//CountryNameCode']
536
+ res.provider='google'
537
+
538
+ #extended -- false if not not available
539
+ res.city = doc.elements['.//LocalityName'].text if doc.elements['.//LocalityName']
540
+ res.state = doc.elements['.//AdministrativeAreaName'].text if doc.elements['.//AdministrativeAreaName']
541
+ res.province = doc.elements['.//SubAdministrativeAreaName'].text if doc.elements['.//SubAdministrativeAreaName']
542
+ res.full_address = doc.elements['.//address'].text if doc.elements['.//address'] # google provides it
543
+ res.zip = doc.elements['.//PostalCodeNumber'].text if doc.elements['.//PostalCodeNumber']
544
+ res.street_address = doc.elements['.//ThoroughfareName'].text if doc.elements['.//ThoroughfareName']
545
+ res.country = doc.elements['.//CountryName'].text if doc.elements['.//CountryName']
546
+ res.district = doc.elements['.//DependentLocalityName'].text if doc.elements['.//DependentLocalityName']
547
+ # Translate accuracy into Yahoo-style token address, street, zip, zip+4, city, state, country
548
+ # For Google, 1=low accuracy, 8=high accuracy
549
+ address_details=doc.elements['.//*[local-name() = "AddressDetails"]']
550
+ res.accuracy = address_details ? address_details.attributes['Accuracy'].to_i : 0
551
+ res.precision=%w{unknown country state state city zip zip+4 street address building}[res.accuracy]
552
+
553
+ # google returns a set of suggested boundaries for the geocoded result
554
+ if suggested_bounds = doc.elements['//LatLonBox']
555
+ res.suggested_bounds = Bounds.normalize(
556
+ [suggested_bounds.attributes['south'], suggested_bounds.attributes['west']],
557
+ [suggested_bounds.attributes['north'], suggested_bounds.attributes['east']])
558
+ end
559
+
560
+ res.success=true
561
+
562
+ return res
563
+ end
564
+ end
565
+
566
+
567
+ # -------------------------------------------------------------------------------------------
568
+ # IP Geocoders
569
+ # -------------------------------------------------------------------------------------------
570
+
571
+ # Provides geocoding based upon an IP address. The underlying web service is geoplugin.net
572
+ class GeoPluginGeocoder < Geocoder
573
+ private
574
+
575
+ def self.do_geocode(ip, options = {})
576
+ return GeoLoc.new unless /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip)
577
+ response = self.call_geocoder_service("http://www.geoplugin.net/xml.gp?ip=#{ip}")
578
+ return response.is_a?(Net::HTTPSuccess) ? parse_xml(response.body) : GeoLoc.new
579
+ rescue
580
+ logger.error "Caught an error during GeoPluginGeocoder geocoding call: "+$!
581
+ return GeoLoc.new
582
+ end
583
+
584
+ def self.parse_xml(xml)
585
+ xml = REXML::Document.new(xml)
586
+ geo = GeoLoc.new
587
+ geo.provider='geoPlugin'
588
+ geo.city = xml.elements['//geoplugin_city'].text
589
+ geo.state = xml.elements['//geoplugin_region'].text
590
+ geo.country_code = xml.elements['//geoplugin_countryCode'].text
591
+ geo.lat = xml.elements['//geoplugin_latitude'].text.to_f
592
+ geo.lng = xml.elements['//geoplugin_longitude'].text.to_f
593
+ geo.success = !!geo.city && !geo.city.empty?
594
+ return geo
595
+ end
596
+ end
597
+
598
+ # Provides geocoding based upon an IP address. The underlying web service is a hostip.info
599
+ # which sources their data through a combination of publicly available information as well
600
+ # as community contributions.
601
+ class IpGeocoder < Geocoder
602
+
603
+ # A number of non-routable IP ranges.
604
+ #
605
+ # --
606
+ # Sources for these:
607
+ # RFC 3330: Special-Use IPv4 Addresses
608
+ # The bogon list: http://www.cymru.com/Documents/bogon-list.html
609
+
610
+ NON_ROUTABLE_IP_RANGES = [
611
+ IPAddr.new('0.0.0.0/8'), # "This" Network
612
+ IPAddr.new('10.0.0.0/8'), # Private-Use Networks
613
+ IPAddr.new('14.0.0.0/8'), # Public-Data Networks
614
+ IPAddr.new('127.0.0.0/8'), # Loopback
615
+ IPAddr.new('169.254.0.0/16'), # Link local
616
+ IPAddr.new('172.16.0.0/12'), # Private-Use Networks
617
+ IPAddr.new('192.0.2.0/24'), # Test-Net
618
+ IPAddr.new('192.168.0.0/16'), # Private-Use Networks
619
+ IPAddr.new('198.18.0.0/15'), # Network Interconnect Device Benchmark Testing
620
+ IPAddr.new('224.0.0.0/4'), # Multicast
621
+ IPAddr.new('240.0.0.0/4') # Reserved for future use
622
+ ].freeze
623
+
624
+ private
625
+
626
+ # Given an IP address, returns a GeoLoc instance which contains latitude,
627
+ # longitude, city, and country code. Sets the success attribute to false if the ip
628
+ # parameter does not match an ip address.
629
+ def self.do_geocode(ip, options = {})
630
+ return GeoLoc.new unless /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip)
631
+ return GeoLoc.new if self.private_ip_address?(ip)
632
+ url = "http://api.hostip.info/get_html.php?ip=#{ip}&position=true"
633
+ response = self.call_geocoder_service(url)
634
+ response.is_a?(Net::HTTPSuccess) ? parse_body(response.body) : GeoLoc.new
635
+ rescue
636
+ logger.error "Caught an error during HostIp geocoding call: "+$!
637
+ return GeoLoc.new
638
+ end
639
+
640
+ # Converts the body to YAML since its in the form of:
641
+ #
642
+ # Country: UNITED STATES (US)
643
+ # City: Sugar Grove, IL
644
+ # Latitude: 41.7696
645
+ # Longitude: -88.4588
646
+ #
647
+ # then instantiates a GeoLoc instance to populate with location data.
648
+ def self.parse_body(body) # :nodoc:
649
+ yaml = YAML.load(body)
650
+ res = GeoLoc.new
651
+ res.provider = 'hostip'
652
+ res.city, res.state = yaml['City'].split(', ')
653
+ country, res.country_code = yaml['Country'].split(' (')
654
+ res.lat = yaml['Latitude']
655
+ res.lng = yaml['Longitude']
656
+ res.country_code.chop!
657
+ res.success = !(res.city =~ /\(.+\)/)
658
+ res
659
+ end
660
+
661
+ # Checks whether the IP address belongs to a private address range.
662
+ #
663
+ # This function is used to reduce the number of useless queries made to
664
+ # the geocoding service. Such queries can occur frequently during
665
+ # integration tests.
666
+ def self.private_ip_address?(ip)
667
+ return NON_ROUTABLE_IP_RANGES.any? { |range| range.include?(ip) }
668
+ end
669
+ end
670
+
671
+ # -------------------------------------------------------------------------------------------
672
+ # The Multi Geocoder
673
+ # -------------------------------------------------------------------------------------------
674
+
675
+ # Provides methods to geocode with a variety of geocoding service providers, plus failover
676
+ # among providers in the order you configure. When 2nd parameter is set 'true', perform
677
+ # ip location lookup with 'address' as the ip address.
678
+ #
679
+ # Goal:
680
+ # - homogenize the results of multiple geocoders
681
+ #
682
+ # Limitations:
683
+ # - currently only provides the first result. Sometimes geocoders will return multiple results.
684
+ # - currently discards the "accuracy" component of the geocoding calls
685
+ class MultiGeocoder < Geocoder
686
+
687
+ private
688
+ # This method will call one or more geocoders in the order specified in the
689
+ # configuration until one of the geocoders work.
690
+ #
691
+ # The failover approach is crucial for production-grade apps, but is rarely used.
692
+ # 98% of your geocoding calls will be successful with the first call
693
+ def self.do_geocode(address, options = {})
694
+ geocode_ip = /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.match(address)
695
+ provider_order = geocode_ip ? Geokit::Geocoders::ip_provider_order : Geokit::Geocoders::provider_order
696
+
697
+ provider_order.each do |provider|
698
+ begin
699
+ klass = Geokit::Geocoders.const_get "#{Geokit::Inflector::camelize(provider.to_s)}Geocoder"
700
+ res = klass.send :geocode, address, options
701
+ return res if res.success?
702
+ rescue
703
+ logger.error("Something has gone very wrong during geocoding, OR you have configured an invalid class name in Geokit::Geocoders::provider_order. Address: #{address}. Provider: #{provider}")
704
+ end
705
+ end
706
+ # If we get here, we failed completely.
707
+ GeoLoc.new
708
+ end
709
+
710
+ # This method will call one or more geocoders in the order specified in the
711
+ # configuration until one of the geocoders work, only this time it's going
712
+ # to try to reverse geocode a geographical point.
713
+ def self.do_reverse_geocode(latlng)
714
+ Geokit::Geocoders::provider_order.each do |provider|
715
+ begin
716
+ klass = Geokit::Geocoders.const_get "#{Geokit::Inflector::camelize(provider.to_s)}Geocoder"
717
+ res = klass.send :reverse_geocode, latlng
718
+ return res if res.success?
719
+ rescue
720
+ logger.error("Something has gone very wrong during reverse geocoding, OR you have configured an invalid class name in Geokit::Geocoders::provider_order. LatLng: #{latlng}. Provider: #{provider}")
721
+ end
722
+ end
723
+ # If we get here, we failed completely.
724
+ GeoLoc.new
725
+ end
726
+ end
727
+ end
728
+ end
@@ -0,0 +1,3 @@
1
+ module Geokit
2
+ VERSION = "0.0.5"
3
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geokit-premier
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
5
- prerelease: false
4
+ hash: 21
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 4
10
- version: 0.0.4
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andrew Forward (forked project from Andre Lewis and Bill Eisenhauer)
@@ -15,51 +15,155 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2009-08-02 00:00:00 -04:00
18
+ date: 2011-01-19 00:00:00 -05:00
19
19
  default_executable:
20
- dependencies: []
21
-
22
- description: Geokit Premier Gem
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: json_pure
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: hoe
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: rspec
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: autotest
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :development
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: ZenTest
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :development
90
+ version_requirements: *id005
91
+ - !ruby/object:Gem::Dependency
92
+ name: standalone_migrations
93
+ prerelease: false
94
+ requirement: &id006 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ type: :development
104
+ version_requirements: *id006
105
+ - !ruby/object:Gem::Dependency
106
+ name: mysql
107
+ prerelease: false
108
+ requirement: &id007 !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ hash: 3
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ type: :development
118
+ version_requirements: *id007
119
+ description: Enhanced the google geocoder to take advantage of the premier account offering
23
120
  email:
24
121
  - aforward@gmail.com
25
122
  executables: []
26
123
 
27
124
  extensions: []
28
125
 
29
- extra_rdoc_files:
30
- - Manifest.txt
31
- - README.markdown
126
+ extra_rdoc_files: []
127
+
32
128
  files:
129
+ - .gitignore
130
+ - Gemfile
131
+ - Gemfile.lock
132
+ - History.txt
33
133
  - Manifest.txt
34
134
  - README.markdown
35
135
  - Rakefile
36
- - lib/geokit/geocoders.rb
136
+ - autotest/discover.rb
137
+ - geokit-premier-0.0.4.gem
138
+ - geokit-premier.gemspec
37
139
  - lib/geokit.rb
140
+ - lib/geokit/geocoders.rb
141
+ - lib/geokit/geocoders_mine.rb
38
142
  - lib/geokit/mappable.rb
143
+ - lib/geokit/version.rb
39
144
  - spec/geocoder_spec.rb
40
145
  - spec/spec_helper.rb
41
146
  - test/test_base_geocoder.rb
42
147
  - test/test_bounds.rb
43
148
  - test/test_ca_geocoder.rb
44
149
  - test/test_geoloc.rb
45
- - test/test_google_geocoder.rb
46
- - test/test_latlng.rb
47
- - test/test_multi_geocoder.rb
48
- - test/test_us_geocoder.rb
49
- - test/test_yahoo_geocoder.rb
50
150
  - test/test_geoplugin_geocoder.rb
151
+ - test/test_google_geocoder.rb
51
152
  - test/test_google_reverse_geocoder.rb
52
153
  - test/test_inflector.rb
53
154
  - test/test_ipgeocoder.rb
155
+ - test/test_latlng.rb
156
+ - test/test_multi_geocoder.rb
54
157
  - test/test_multi_ip_geocoder.rb
158
+ - test/test_us_geocoder.rb
159
+ - test/test_yahoo_geocoder.rb
55
160
  has_rdoc: true
56
- homepage: http://github.com/aforward/geokit-gem
161
+ homepage: https://github.com/aforward/geokit-premier-gem
57
162
  licenses: []
58
163
 
59
164
  post_install_message:
60
- rdoc_options:
61
- - --main
62
- - README.markdown
165
+ rdoc_options: []
166
+
63
167
  require_paths:
64
168
  - lib
65
169
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -83,12 +187,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
187
  requirements: []
84
188
 
85
189
  rubyforge_project:
86
- rubygems_version: 1.3.7
190
+ rubygems_version: 1.4.1
87
191
  signing_key:
88
- specification_version: 2
89
- summary: none
192
+ specification_version: 3
193
+ summary: Enables google geocoding using a premier account
90
194
  test_files:
91
195
  - spec/geocoder_spec.rb
196
+ - spec/spec_helper.rb
92
197
  - test/test_base_geocoder.rb
93
198
  - test/test_bounds.rb
94
199
  - test/test_ca_geocoder.rb