geokit-premier 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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