ggeocode 0.0.1

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.
Files changed (4) hide show
  1. data/README +16 -0
  2. data/Rakefile +364 -0
  3. data/lib/ggeocode.rb +166 -0
  4. metadata +69 -0
data/README ADDED
@@ -0,0 +1,16 @@
1
+ NAME
2
+ ggeocode
3
+
4
+ SYNOPSIS
5
+ require 'ggeocode'
6
+
7
+ hash = GGeocode.geocode('boulder, co')
8
+ hash = GGeocode.rgeocode('40.0149856,-105.2705456')
9
+
10
+ INSTALL
11
+ gem install ggeocode
12
+
13
+ DESCRIPTION
14
+ a simple interface to google's new geocoding api
15
+
16
+ see http://code.google.com/apis/maps/documentation/geocoding/
data/Rakefile ADDED
@@ -0,0 +1,364 @@
1
+ This.rubyforge_project = 'codeforpeople'
2
+ This.author = "Ara T. Howard"
3
+ This.email = "ara.t.howard@gmail.com"
4
+ This.homepage = "http://github.com/ahoward/#{ This.lib }"
5
+
6
+
7
+ task :default do
8
+ puts((Rake::Task.tasks.map{|task| task.name.gsub(/::/,':')} - ['default']).sort)
9
+ end
10
+
11
+ task :test do
12
+ run_tests!
13
+ end
14
+
15
+ namespace :test do
16
+ task(:unit){ run_tests!(:unit) }
17
+ task(:functional){ run_tests!(:functional) }
18
+ task(:integration){ run_tests!(:integration) }
19
+ end
20
+
21
+ def run_tests!(which = nil)
22
+ which ||= '**'
23
+ test_dir = File.join(This.dir, "test")
24
+ test_glob ||= File.join(test_dir, "#{ which }/**_test.rb")
25
+ test_rbs = Dir.glob(test_glob).sort
26
+
27
+ div = ('=' * 119)
28
+ line = ('-' * 119)
29
+ helper = "-r ./test/helper.rb" if test(?e, "./test/helper.rb")
30
+
31
+ test_rbs.each_with_index do |test_rb, index|
32
+ testno = index + 1
33
+ command = "#{ This.ruby } -I ./lib -I ./test/lib #{ helper } #{ test_rb }"
34
+
35
+ puts
36
+ say(div, :color => :cyan, :bold => true)
37
+ say("@#{ testno } => ", :bold => true, :method => :print)
38
+ say(command, :color => :cyan, :bold => true)
39
+ say(line, :color => :cyan, :bold => true)
40
+
41
+ system(command)
42
+
43
+ say(line, :color => :cyan, :bold => true)
44
+
45
+ status = $?.exitstatus
46
+
47
+ if status.zero?
48
+ say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print)
49
+ say("SUCCESS", :color => :green, :bold => true)
50
+ else
51
+ say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print)
52
+ say("FAILURE", :color => :red, :bold => true)
53
+ end
54
+ say(line, :color => :cyan, :bold => true)
55
+
56
+ exit(status) unless status.zero?
57
+ end
58
+ end
59
+
60
+
61
+ task :gemspec do
62
+ ignore_extensions = 'git', 'svn', 'tmp', /sw./, 'bak', 'gem'
63
+ ignore_directories = %w[ pkg ]
64
+ ignore_files = %w[ test/log ]
65
+
66
+ shiteless =
67
+ lambda do |list|
68
+ list.delete_if do |entry|
69
+ next unless test(?e, entry)
70
+ extension = File.basename(entry).split(%r/[.]/).last
71
+ ignore_extensions.any?{|ext| ext === extension}
72
+ end
73
+ list.delete_if do |entry|
74
+ next unless test(?d, entry)
75
+ dirname = File.expand_path(entry)
76
+ ignore_directories.any?{|dir| File.expand_path(dir) == dirname}
77
+ end
78
+ list.delete_if do |entry|
79
+ next unless test(?f, entry)
80
+ filename = File.expand_path(entry)
81
+ ignore_files.any?{|file| File.expand_path(file) == filename}
82
+ end
83
+ end
84
+
85
+ lib = This.lib
86
+ object = This.object
87
+ version = This.version
88
+ files = shiteless[Dir::glob("**/**")]
89
+ executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
90
+ has_rdoc = true #File.exist?('doc')
91
+ test_files = "test/#{ lib }.rb" if File.file?("test/#{ lib }.rb")
92
+ summary = object.respond_to?(:summary) ? object.summary : "summary: #{ lib } kicks the ass"
93
+ description = object.respond_to?(:description) ? object.description : "description: #{ lib } kicks the ass"
94
+
95
+ if This.extensions.nil?
96
+ This.extensions = []
97
+ extensions = This.extensions
98
+ %w( Makefile configure extconf.rb ).each do |ext|
99
+ extensions << ext if File.exists?(ext)
100
+ end
101
+ end
102
+ extensions = [extensions].flatten.compact
103
+
104
+ template =
105
+ if test(?e, 'gemspec.erb')
106
+ Template{ IO.read('gemspec.erb') }
107
+ else
108
+ Template {
109
+ <<-__
110
+ ## #{ lib }.gemspec
111
+ #
112
+
113
+ Gem::Specification::new do |spec|
114
+ spec.name = #{ lib.inspect }
115
+ spec.version = #{ version.inspect }
116
+ spec.platform = Gem::Platform::RUBY
117
+ spec.summary = #{ lib.inspect }
118
+ spec.description = #{ description.inspect }
119
+
120
+ spec.files = #{ files.inspect }
121
+ spec.executables = #{ executables.inspect }
122
+
123
+ spec.require_path = "lib"
124
+
125
+ spec.has_rdoc = #{ has_rdoc.inspect }
126
+ spec.test_files = #{ test_files.inspect }
127
+
128
+ # spec.add_dependency 'lib', '>= version'
129
+
130
+ spec.extensions.push(*#{ extensions.inspect })
131
+
132
+ spec.rubyforge_project = #{ This.rubyforge_project.inspect }
133
+ spec.author = #{ This.author.inspect }
134
+ spec.email = #{ This.email.inspect }
135
+ spec.homepage = #{ This.homepage.inspect }
136
+ end
137
+ __
138
+ }
139
+ end
140
+
141
+ Fu.mkdir_p(This.pkgdir)
142
+ This.gemspec = File.join(This.dir, "#{ This.lib }.gemspec") #File.join(This.pkgdir, "gemspec.rb")
143
+ open("#{ This.gemspec }", "w"){|fd| fd.puts(template)}
144
+ end
145
+
146
+ task :gem => [:clean, :gemspec] do
147
+ Fu.mkdir_p(This.pkgdir)
148
+ before = Dir['*.gem']
149
+ cmd = "gem build #{ This.gemspec }"
150
+ `#{ cmd }`
151
+ after = Dir['*.gem']
152
+ gem = ((after - before).first || after.first) or abort('no gem!')
153
+ Fu.mv gem, This.pkgdir
154
+ This.gem = File.basename(gem)
155
+ end
156
+
157
+ task :readme do
158
+ samples = ''
159
+ prompt = '~ > '
160
+ lib = This.lib
161
+ version = This.version
162
+
163
+ Dir['sample*/*'].sort.each do |sample|
164
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
165
+
166
+ cmd = "cat #{ sample }"
167
+ samples << Util.indent(prompt + cmd, 2) << "\n\n"
168
+ samples << Util.indent(`#{ cmd }`, 4) << "\n"
169
+
170
+ cmd = "ruby #{ sample }"
171
+ samples << Util.indent(prompt + cmd, 2) << "\n\n"
172
+
173
+ cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -I ./lib #{ sample })'"
174
+ samples << Util.indent(`#{ cmd } 2>&1`, 4) << "\n"
175
+ end
176
+
177
+ template =
178
+ if test(?e, 'readme.erb')
179
+ Template{ IO.read('readme.erb') }
180
+ else
181
+ Template {
182
+ <<-__
183
+ NAME
184
+ #{ lib }
185
+
186
+ DESCRIPTION
187
+
188
+ INSTALL
189
+ gem install #{ lib }
190
+
191
+ SAMPLES
192
+ #{ samples }
193
+ __
194
+ }
195
+ end
196
+
197
+ open("README", "w"){|fd| fd.puts template}
198
+ end
199
+
200
+
201
+ task :clean do
202
+ Dir[File.join(This.pkgdir, '**/**')].each{|entry| Fu.rm_rf(entry)}
203
+ end
204
+
205
+
206
+ task :release => [:clean, :gemspec, :gem] do
207
+ gems = Dir[File.join(This.pkgdir, '*.gem')].flatten
208
+ raise "which one? : #{ gems.inspect }" if gems.size > 1
209
+ raise "no gems?" if gems.size < 1
210
+ cmd = "rubyforge login && rubyforge add_release #{ This.rubyforge_project } #{ This.lib } #{ This.version } #{ This.pkgdir }/#{ This.gem }"
211
+ puts cmd
212
+ system cmd
213
+ cmd = "gem push #{ This.pkgdir }/#{ This.gem }"
214
+ puts cmd
215
+ system cmd
216
+ end
217
+
218
+
219
+
220
+
221
+
222
+ BEGIN {
223
+ # support for this rakefile
224
+ #
225
+ $VERBOSE = nil
226
+
227
+ require 'ostruct'
228
+ require 'erb'
229
+ require 'fileutils'
230
+ require 'rbconfig'
231
+
232
+ # fu shortcut
233
+ #
234
+ Fu = FileUtils
235
+
236
+ # cache a bunch of stuff about this rakefile/environment
237
+ #
238
+ This = OpenStruct.new
239
+
240
+ This.file = File.expand_path(__FILE__)
241
+ This.dir = File.dirname(This.file)
242
+ This.pkgdir = File.join(This.dir, 'pkg')
243
+
244
+ # grok lib
245
+ #
246
+ lib = ENV['LIB']
247
+ unless lib
248
+ lib = File.basename(Dir.pwd).sub(/[-].*$/, '')
249
+ end
250
+ This.lib = lib
251
+
252
+ # grok version
253
+ #
254
+ version = ENV['VERSION']
255
+ unless version
256
+ require "./lib/#{ This.lib }"
257
+ This.name = lib.capitalize
258
+ This.object = eval(This.name)
259
+ version = This.object.send(:version)
260
+ end
261
+ This.version = version
262
+
263
+ # we need to know the name of the lib an it's version
264
+ #
265
+ abort('no lib') unless This.lib
266
+ abort('no version') unless This.version
267
+
268
+ # discover full path to this ruby executable
269
+ #
270
+ c = Config::CONFIG
271
+ bindir = c["bindir"] || c['BINDIR']
272
+ ruby_install_name = c['ruby_install_name'] || c['RUBY_INSTALL_NAME'] || 'ruby'
273
+ ruby_ext = c['EXEEXT'] || ''
274
+ ruby = File.join(bindir, (ruby_install_name + ruby_ext))
275
+ This.ruby = ruby
276
+
277
+ # some utils
278
+ #
279
+ module Util
280
+ def indent(s, n = 2)
281
+ s = unindent(s)
282
+ ws = ' ' * n
283
+ s.gsub(%r/^/, ws)
284
+ end
285
+
286
+ def unindent(s)
287
+ indent = nil
288
+ s.each_line do |line|
289
+ next if line =~ %r/^\s*$/
290
+ indent = line[%r/^\s*/] and break
291
+ end
292
+ indent ? s.gsub(%r/^#{ indent }/, "") : s
293
+ end
294
+ extend self
295
+ end
296
+
297
+ # template support
298
+ #
299
+ class Template
300
+ def initialize(&block)
301
+ @block = block.binding
302
+ @template = block.call.to_s
303
+ end
304
+ def expand(b=nil)
305
+ ERB.new(Util.unindent(@template)).result(b||@block)
306
+ end
307
+ alias_method 'to_s', 'expand'
308
+ end
309
+ def Template(*args, &block) Template.new(*args, &block) end
310
+
311
+ # colored console output support
312
+ #
313
+ This.ansi = {
314
+ :clear => "\e[0m",
315
+ :reset => "\e[0m",
316
+ :erase_line => "\e[K",
317
+ :erase_char => "\e[P",
318
+ :bold => "\e[1m",
319
+ :dark => "\e[2m",
320
+ :underline => "\e[4m",
321
+ :underscore => "\e[4m",
322
+ :blink => "\e[5m",
323
+ :reverse => "\e[7m",
324
+ :concealed => "\e[8m",
325
+ :black => "\e[30m",
326
+ :red => "\e[31m",
327
+ :green => "\e[32m",
328
+ :yellow => "\e[33m",
329
+ :blue => "\e[34m",
330
+ :magenta => "\e[35m",
331
+ :cyan => "\e[36m",
332
+ :white => "\e[37m",
333
+ :on_black => "\e[40m",
334
+ :on_red => "\e[41m",
335
+ :on_green => "\e[42m",
336
+ :on_yellow => "\e[43m",
337
+ :on_blue => "\e[44m",
338
+ :on_magenta => "\e[45m",
339
+ :on_cyan => "\e[46m",
340
+ :on_white => "\e[47m"
341
+ }
342
+ def say(phrase, *args)
343
+ options = args.last.is_a?(Hash) ? args.pop : {}
344
+ options[:color] = args.shift.to_s.to_sym unless args.empty?
345
+ keys = options.keys
346
+ keys.each{|key| options[key.to_s.to_sym] = options.delete(key)}
347
+
348
+ color = options[:color]
349
+ bold = options.has_key?(:bold)
350
+
351
+ parts = [phrase]
352
+ parts.unshift(This.ansi[color]) if color
353
+ parts.unshift(This.ansi[:bold]) if bold
354
+ parts.push(This.ansi[:clear]) if parts.size > 1
355
+
356
+ method = options[:method] || :puts
357
+
358
+ Kernel.send(method, parts.join)
359
+ end
360
+
361
+ # always run out of the project dir
362
+ #
363
+ Dir.chdir(This.dir)
364
+ }
data/lib/ggeocode.rb ADDED
@@ -0,0 +1,166 @@
1
+ module GGeocode
2
+
3
+ GGeocode::Version = '0.0.1'
4
+
5
+ def GGeocode.version
6
+ GGeocode::Version
7
+ end
8
+
9
+ require 'net/http'
10
+ require 'uri'
11
+ require 'cgi'
12
+
13
+ begin
14
+ require 'rubygems'
15
+ gem 'yajl-ruby'
16
+ gem 'map'
17
+ rescue LoadError
18
+ nil
19
+ end
20
+
21
+ require 'yajl/json_gem'
22
+ require 'map'
23
+
24
+
25
+ def geocode(string)
26
+ response = get(url_for(:address => string))
27
+ result_for(response)
28
+ end
29
+
30
+ def reverse_geocode(string)
31
+ response = get(url_for(:latlng => string))
32
+ result_for(response)
33
+ end
34
+ alias_method('rgeocode', 'reverse_geocode')
35
+
36
+ module Response
37
+ attr_accessor :response
38
+
39
+ def body
40
+ response.body
41
+ end
42
+ end
43
+
44
+ def result_for(response)
45
+ return nil unless response
46
+ hash = JSON.parse(response.body)
47
+ return nil unless hash['status']=='OK'
48
+ map = Map.new
49
+ map.extend(Response)
50
+ map.response = response
51
+ map['status'] = hash['status']
52
+ map['results'] = hash['results']
53
+ map
54
+ end
55
+
56
+ Url = URI.parse("http://maps.google.com/maps/api/geocode/json?")
57
+
58
+ def url_for(options = {})
59
+ options[:sensor] = false unless options.has_key?(:sensor)
60
+ url = Url.dup
61
+ url.query = query_for(options)
62
+ url
63
+ end
64
+
65
+ def query_for(options = {})
66
+ pairs = []
67
+ options.each do |key, values|
68
+ key = key.to_s
69
+ values = [values].flatten
70
+ values.each do |value|
71
+ value = value.to_s
72
+ if value.empty?
73
+ pairs << [ CGI.escape(key) ]
74
+ else
75
+ pairs << [ CGI.escape(key), CGI.escape(value) ].join('=')
76
+ end
77
+ end
78
+ end
79
+ pairs.replace pairs.sort_by{|pair| pair.size}
80
+ pairs.join('&')
81
+ end
82
+
83
+ def get(url)
84
+ url = URI.parse(url.to_s) unless url.is_a?(URI)
85
+ begin
86
+ Net::HTTP.get_response(url)
87
+ rescue SocketError, TimeoutError
88
+ return nil
89
+ end
90
+ end
91
+
92
+ extend(GGeocode)
93
+ end
94
+
95
+ Ggeocode = GGeocode
96
+
97
+
98
+ if $0 == __FILE__
99
+ require 'pp'
100
+
101
+ pp(GGeocode.geocode('boulder, co'))
102
+ pp(GGeocode.rgeocode('40.0149856,-105.2705456'))
103
+ end
104
+
105
+
106
+
107
+
108
+
109
+ __END__
110
+
111
+ {
112
+ "status": "OK",
113
+
114
+ "results": [ {
115
+ "types": [ "locality", "political" ],
116
+
117
+ "formatted_address": "Boulder, CO, USA",
118
+
119
+ "address_components": [ {
120
+ "long_name": "Boulder",
121
+ "short_name": "Boulder",
122
+ "types": [ "locality", "political" ]
123
+ }, {
124
+ "long_name": "Boulder",
125
+ "short_name": "Boulder",
126
+ "types": [ "administrative_area_level_2", "political" ]
127
+ }, {
128
+ "long_name": "Colorado",
129
+ "short_name": "CO",
130
+ "types": [ "administrative_area_level_1", "political" ]
131
+ }, {
132
+ "long_name": "United States",
133
+ "short_name": "US",
134
+ "types": [ "country", "political" ]
135
+ } ],
136
+
137
+ "geometry": {
138
+ "location": {
139
+ "lat": 40.0149856,
140
+ "lng": -105.2705456
141
+ },
142
+ "location_type": "APPROXIMATE",
143
+ "viewport": {
144
+ "southwest": {
145
+ "lat": 39.9465862,
146
+ "lng": -105.3986050
147
+ },
148
+ "northeast": {
149
+ "lat": 40.0833165,
150
+ "lng": -105.1424862
151
+ }
152
+ },
153
+ "bounds": {
154
+ "southwest": {
155
+ "lat": 39.9640689,
156
+ "lng": -105.3017580
157
+ },
158
+ "northeast": {
159
+ "lat": 40.0945509,
160
+ "lng": -105.1781970
161
+ }
162
+ }
163
+ }
164
+ } ]
165
+ }
166
+
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ggeocode
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Ara T. Howard
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-02 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: "description: ggeocode kicks the ass"
23
+ email: ara.t.howard@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/ggeocode.rb
32
+ - Rakefile
33
+ - README
34
+ has_rdoc: true
35
+ homepage: http://github.com/ahoward/ggeocode
36
+ licenses: []
37
+
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ hash: 3
49
+ segments:
50
+ - 0
51
+ version: "0"
52
+ required_rubygems_version: !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
+ requirements: []
62
+
63
+ rubyforge_project: codeforpeople
64
+ rubygems_version: 1.4.2
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: ggeocode
68
+ test_files: []
69
+