barometer 0.1.0 → 0.2.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.
- data/LICENSE +1 -1
- data/README.rdoc +53 -7
- data/VERSION.yml +2 -2
- data/bin/barometer +405 -53
- data/lib/barometer/data/geo.rb +3 -1
- data/lib/barometer/extensions/graticule.rb +3 -2
- data/lib/barometer/query.rb +57 -8
- data/lib/barometer/services/wunderground.rb +3 -2
- data/lib/barometer/weather.rb +45 -42
- data/lib/webometer/public/css/master.css +254 -0
- data/lib/webometer/public/css/print.css +90 -0
- data/lib/webometer/public/css/syntax.css +60 -0
- data/lib/webometer/public/images/go.png +0 -0
- data/lib/webometer/public/images/link-out.gif +0 -0
- data/lib/webometer/views/contributing.erb +32 -0
- data/lib/webometer/views/forecast.erb +14 -0
- data/lib/webometer/views/index.erb +66 -0
- data/lib/webometer/views/layout.erb +38 -0
- data/lib/webometer/views/measurement.erb +88 -0
- data/lib/webometer/views/readme.erb +338 -0
- data/lib/webometer/webometer.rb +34 -0
- data/spec/barometer_spec.rb +1 -1
- data/spec/data_geo_spec.rb +4 -0
- data/spec/fixtures/geocode_ksfo.xml +1 -0
- data/spec/query_spec.rb +49 -5
- data/spec/service_wunderground_spec.rb +1 -1
- data/spec/spec_helper.rb +25 -0
- data/spec/weather_spec.rb +168 -0
- metadata +20 -2
data/LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -8,28 +8,43 @@ information, or they can be used in a hierarchical configuration where lower
|
|
8
8
|
preferred weather services are only used if previous services are
|
9
9
|
unavailable.
|
10
10
|
|
11
|
+
== version
|
12
|
+
|
13
|
+
Version 0.1.0 is the current release of this gem.
|
14
|
+
The gem is available from github (attack-barometer) or rubyforge (barometer).
|
15
|
+
It is fully functional (for three weather service APIs).
|
16
|
+
|
11
17
|
== status
|
12
18
|
|
13
19
|
Currently this project is in development and will only work for a few weather
|
14
20
|
services (wunderground, google, yahoo).
|
15
21
|
|
16
|
-
Features to be added
|
17
|
-
- gem setup/config, apply to rubyforge
|
18
|
-
|
19
|
-
Features to be added in future releases:
|
22
|
+
Features to be added next:
|
20
23
|
- even more weather service drivers (noaa, weather.com, weatherbug)
|
21
|
-
- ability to query multiple services and combine/average the results
|
22
|
-
- support iaco as a query format
|
23
24
|
|
24
25
|
= dependencies
|
25
26
|
|
27
|
+
=== Google API key
|
28
|
+
|
29
|
+
In most cases you will need to have a free google geocode api key.
|
30
|
+
Get one here: http://code.google.com/apis/maps/signup.html
|
31
|
+
Then put it in the file '~/.barometer' by adding the line:
|
32
|
+
geocode_google: YOUR_KEY_HERE
|
33
|
+
|
34
|
+
You will need this for:
|
35
|
+
- using the Barometer gem (unless you use queries that are directly supported
|
36
|
+
by the weather source API, ie yahoo will take a zip code directly and doesn't
|
37
|
+
require any geocoding)
|
38
|
+
- running the Barometer binary
|
39
|
+
- running the Barometer Web Demo
|
40
|
+
|
26
41
|
=== HTTParty
|
27
42
|
|
28
43
|
Why? HTTParty was created and designed specifically for consuming web services.
|
29
44
|
I choose to use this over using the Net::HTTP library directly to allow for
|
30
45
|
faster development of this project.
|
31
46
|
|
32
|
-
HTTParty is also extended to include configurable
|
47
|
+
HTTParty is also extended to include configurable Timeout support.
|
33
48
|
|
34
49
|
=== tzinfo
|
35
50
|
|
@@ -96,6 +111,18 @@ You can use barometer from the command line.
|
|
96
111
|
# barometer berlin
|
97
112
|
|
98
113
|
This will output the weather information for the given query.
|
114
|
+
See the help for more command line information.
|
115
|
+
|
116
|
+
# barometer -h
|
117
|
+
|
118
|
+
=== web demo
|
119
|
+
|
120
|
+
There is a Sinatra application that demos the functionality of Barometer,
|
121
|
+
and provides Barometer information. Start this local demo with:
|
122
|
+
|
123
|
+
# barometer -w
|
124
|
+
|
125
|
+
NOTE: This requires the gems "sinatra" and "vegas".
|
99
126
|
|
100
127
|
=== fail
|
101
128
|
|
@@ -188,6 +215,25 @@ the data as shown in the above examples.
|
|
188
215
|
|
189
216
|
puts weather.source(:wunderground).for(time).low.f
|
190
217
|
|
218
|
+
== averages
|
219
|
+
|
220
|
+
If you consume more then one weather service, Barometer can provide averages
|
221
|
+
for the values (currently only for the 'current' values and not the forecasted
|
222
|
+
values).
|
223
|
+
|
224
|
+
require 'barometer'
|
225
|
+
|
226
|
+
Barometer.google_geocode_key = "THE_GOOGLE_API_KEY"
|
227
|
+
# use yahoo and wunderground
|
228
|
+
Barometer.selection = { 1 => [:yahoo, :wunderground] }
|
229
|
+
|
230
|
+
barometer = Barometer.new("90210")
|
231
|
+
weather = barometer.measure
|
232
|
+
|
233
|
+
puts weather.temperture
|
234
|
+
|
235
|
+
This will calculate the average temperature as given by :yahoo and :wunderground
|
236
|
+
|
191
237
|
== simple answers
|
192
238
|
|
193
239
|
After you have measured the data, Barometer provides several "simple answer"
|
data/VERSION.yml
CHANGED
data/bin/barometer
CHANGED
@@ -1,63 +1,415 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
|
4
|
-
#
|
5
|
-
#
|
6
|
-
|
7
|
-
#
|
8
|
-
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
2
|
+
|
3
|
+
# == Barometer
|
4
|
+
# This is the command line interface to the barometer gem.
|
5
|
+
#
|
6
|
+
# == Examples
|
7
|
+
# This command will measure the weather for the given query.
|
8
|
+
# barometer berlin
|
9
|
+
#
|
10
|
+
# Other examples:
|
11
|
+
# barometer --yahoo 90210
|
12
|
+
# barometer --verbose 'new york'
|
13
|
+
#
|
14
|
+
# == Local Web Demo
|
15
|
+
# You can easily interact directly with barometer with the command:
|
16
|
+
# barometer -w
|
17
|
+
#
|
18
|
+
# This demo has 2 gem requirements:
|
19
|
+
# - sinatra (tested with 0.9.1.1)
|
20
|
+
# - vegas (tested with 0.0.1)
|
21
|
+
#
|
22
|
+
# == Usage
|
23
|
+
# barometer [options] query
|
24
|
+
#
|
25
|
+
# For help use: barometer -h
|
26
|
+
#
|
27
|
+
# Options:
|
28
|
+
# -v, --version Display the version, then exit
|
29
|
+
# -V, --verbose Verbose output
|
30
|
+
# -t, --timeout seconds until service queries will timeout
|
31
|
+
# -g, --geocode Force Geocoding of query
|
32
|
+
# -m, --metric measure in metric
|
33
|
+
# -i, --imperial measure in imperial
|
34
|
+
# --no-wunderground DONT use default wunderground as source
|
35
|
+
# --yahoo use yahoo as source
|
36
|
+
# --google use google as source
|
37
|
+
# -p, --pop pop threshold used to determine wet?
|
38
|
+
# -s, --wind wind speed threshold used to determine windy?
|
39
|
+
# -a, --at time/date used to determine when to calculate summary
|
40
|
+
#
|
41
|
+
# Web Demo:
|
42
|
+
# -w, --web run web-app with barometer demo
|
43
|
+
# -k, --kill stop the web demo background process
|
44
|
+
# -S, --status show the web demo status
|
45
|
+
#
|
46
|
+
# == Author
|
47
|
+
# Mark G
|
48
|
+
# http://github.com/attack/barometer
|
49
|
+
#
|
50
|
+
# == Copyright
|
51
|
+
# Copyright (c) 2009 Mark G. Licensed under the MIT License:
|
52
|
+
# http://www.opensource.org/licenses/mit-license.php
|
53
|
+
|
54
|
+
require 'rubygems'
|
55
|
+
#require 'barometer'
|
56
|
+
require 'lib/barometer'
|
57
|
+
|
58
|
+
require 'optparse'
|
59
|
+
require 'rdoc/usage'
|
60
|
+
require 'ostruct'
|
61
|
+
require 'time'
|
62
|
+
require 'date'
|
63
|
+
require 'yaml'
|
64
|
+
|
65
|
+
# file where API keys are stored
|
66
|
+
KEY_FILE = File.expand_path(File.join('~', '.barometer'))
|
67
|
+
|
68
|
+
class App
|
69
|
+
VERSION = '0.0.1'
|
70
|
+
|
71
|
+
attr_reader :options
|
72
|
+
|
73
|
+
def initialize(arguments, stdin)
|
74
|
+
@arguments = arguments.dup
|
75
|
+
|
76
|
+
# Set defaults
|
77
|
+
@options = OpenStruct.new
|
78
|
+
@options.timeout = 15
|
79
|
+
@options.geocode = false
|
80
|
+
@options.skip_graticule = false
|
81
|
+
@options.metric = true
|
82
|
+
@options.sources = [:wunderground]
|
83
|
+
@options.verbode = false
|
84
|
+
@options.web = false
|
85
|
+
@options.at = Time.now.utc
|
86
|
+
|
87
|
+
# thresholds
|
88
|
+
@options.windy_m = 10
|
89
|
+
@options.windy_i = 7
|
90
|
+
@options.pop = 50
|
91
|
+
end
|
92
|
+
|
93
|
+
# Parse options, check arguments, then process the command
|
94
|
+
def run
|
95
|
+
if parsed_options? && arguments_valid?
|
96
|
+
puts "Start at #{DateTime.now}\n\n" if @options.verbose
|
97
|
+
output_options if @options.verbose # [Optional]
|
98
|
+
|
99
|
+
process_arguments
|
100
|
+
process_command
|
101
|
+
|
102
|
+
puts "\nFinished at #{DateTime.now}" if @options.verbose
|
103
|
+
else
|
104
|
+
output_usage
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
protected
|
109
|
+
|
110
|
+
# future options
|
111
|
+
#
|
112
|
+
# time: -a --at
|
113
|
+
#
|
114
|
+
def parsed_options?
|
115
|
+
# Specify options
|
116
|
+
opt = OptionParser.new
|
117
|
+
opt.on('-v', '--version') { output_version ; exit 0 }
|
118
|
+
opt.on('-h', '--help') { output_help }
|
119
|
+
opt.on('-V', '--verbose') { @options.verbose = true }
|
120
|
+
opt.on('-a n', '--at n') {|n| @options.at = Time.parse(n.to_s) }
|
121
|
+
opt.on('-t n', '--timeout n') {|n| @options.timeout = n }
|
122
|
+
opt.on('-w', '--web') { @options.web = true; ARGV.shift }
|
123
|
+
opt.on('-g', '--geocode') { @options.geocode = true }
|
124
|
+
opt.on('--skip') { @options.skip_graticule = true }
|
125
|
+
opt.on('-m', '--metric') { @options.metric = true }
|
126
|
+
opt.on('-i', '--imperial') { @options.metric = false }
|
127
|
+
opt.on('--no-wunderground') { @options.sources = @options.sources.delete_if{|s| s == :wunderground} }
|
128
|
+
opt.on('--yahoo') { @options.sources << :yahoo }
|
129
|
+
opt.on('--google') { @options.sources << :google }
|
130
|
+
opt.on('-p n', '--pop n') {|n| @options.pop = n.to_i || 50 }
|
131
|
+
opt.on('-s n', '--wind n') {|n| @options.metric ? @options.windy_m = n.to_f || 10 : @options.windy_i = n.to_f || 7 }
|
132
|
+
|
133
|
+
# pass these onto vegas
|
134
|
+
opt.on('-k', '--kill') { @options.web = true }
|
135
|
+
opt.on('-S', '--status') { @options.web = true }
|
136
|
+
|
137
|
+
opt.parse!(@arguments) rescue return false
|
138
|
+
|
139
|
+
process_options
|
140
|
+
true
|
141
|
+
end
|
142
|
+
|
143
|
+
# Performs post-parse processing on options
|
144
|
+
def process_options
|
145
|
+
Barometer.force_geocode = @options.geocode
|
146
|
+
Barometer.selection = { 1 => @options.sources.uniq }
|
147
|
+
Barometer.skip_graticule = @options.skip_graticule
|
148
|
+
Barometer.timeout = @options.timeout
|
149
|
+
end
|
150
|
+
|
151
|
+
def output_options
|
152
|
+
puts "Options:\n"
|
153
|
+
|
154
|
+
@options.marshal_dump.each do |name, val|
|
155
|
+
puts " #{name} = #{val}"
|
156
|
+
end
|
157
|
+
puts
|
158
|
+
end
|
159
|
+
|
160
|
+
# True if required arguments were provided
|
161
|
+
def arguments_valid?
|
162
|
+
true if (@arguments.length >= 1 || @options.web)
|
163
|
+
end
|
164
|
+
|
165
|
+
# Setup the arguments
|
166
|
+
def process_arguments
|
167
|
+
#puts @arguments.inspect
|
168
|
+
end
|
169
|
+
|
170
|
+
def output_help
|
171
|
+
output_version
|
172
|
+
RDoc::usage() #exits app
|
173
|
+
end
|
174
|
+
|
175
|
+
def output_usage
|
176
|
+
RDoc::usage('usage') # gets usage from comments above
|
177
|
+
end
|
178
|
+
|
179
|
+
def output_version
|
180
|
+
puts "#{File.basename(__FILE__)} version #{VERSION}"
|
181
|
+
end
|
182
|
+
|
183
|
+
def process_command
|
184
|
+
if @options.web
|
185
|
+
run_web_mode(@arguments.join(" "))
|
186
|
+
else
|
187
|
+
barometer = Barometer.new(@arguments.join(" "))
|
188
|
+
begin
|
189
|
+
barometer.measure(@options.metric) if barometer
|
190
|
+
pretty_output(barometer) if barometer.weather
|
191
|
+
rescue Barometer::OutOfSources
|
192
|
+
puts
|
193
|
+
puts " SORRY: your query did not provide any results"
|
194
|
+
puts
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
35
198
|
end
|
36
|
-
|
37
|
-
|
38
|
-
|
199
|
+
|
200
|
+
#
|
201
|
+
# HELPERS
|
202
|
+
#
|
203
|
+
|
204
|
+
@level = 1
|
39
205
|
|
40
206
|
def y(value)
|
41
207
|
value ? "yes" : "no"
|
42
208
|
end
|
43
209
|
|
44
|
-
|
45
|
-
puts
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
puts " --
|
51
|
-
|
210
|
+
def div(char="#")
|
211
|
+
puts char*50
|
212
|
+
end
|
213
|
+
|
214
|
+
def title(title, level=1)
|
215
|
+
@level = level
|
216
|
+
puts "#{" " * @level}-- #{title} --"
|
217
|
+
end
|
218
|
+
|
219
|
+
def value(title, value)
|
220
|
+
puts "#{" " * @level}#{title}: #{value}" unless value.nil?
|
221
|
+
end
|
222
|
+
|
223
|
+
def blank
|
52
224
|
puts
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
225
|
+
end
|
226
|
+
|
227
|
+
def section(title, level=1, show_blank=true)
|
228
|
+
@level = level
|
229
|
+
title(title, level); yield; blank if show_blank
|
230
|
+
end
|
231
|
+
|
232
|
+
def pretty_hash(hash)
|
233
|
+
return unless hash.is_a?(Hash)
|
234
|
+
hash.each { |k,v| value(k,v) }
|
235
|
+
end
|
236
|
+
|
237
|
+
def pretty_summary(s)
|
238
|
+
return unless s
|
239
|
+
section("AVERAGES") do
|
240
|
+
pretty_hash({
|
241
|
+
"humidity" => s.humidity.to_i, "temperature" => s.temperature })
|
242
|
+
end
|
243
|
+
section("SUMMARY#{ " (@ #{@options.at})" if @options.at }") do
|
244
|
+
pretty_hash({
|
245
|
+
"day?" => s.day?(@options.at), "sunny?" => s.sunny?(@options.at),
|
246
|
+
"windy?" => s.windy?(@options.metric ? @options.windy_m : @options.windy_i, @options.at),
|
247
|
+
"wet?" => s.wet?(@options.pop,@options.at) })
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def pretty_query(q)
|
252
|
+
return unless q
|
253
|
+
section("QUERY", 2) do
|
254
|
+
pretty_hash({"Format" => q.format})
|
255
|
+
pretty_hash({
|
256
|
+
"Address" => q.geo.address,
|
257
|
+
"Locality" => q.geo.locality, "Region" => q.geo.region,
|
258
|
+
"Country" => q.geo.country, "Country Code" => q.geo.country_code,
|
259
|
+
"Latitude" => q.geo.latitude, "Longitude" => q.geo.longitude }) if q.geo
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def pretty_location(l)
|
264
|
+
return unless l
|
265
|
+
section("LOCATION", 2) do
|
266
|
+
pretty_hash({
|
267
|
+
"ID" => l.id, "Name" => l.name,
|
268
|
+
"City" => l.city, "State Name" => l.state_name,
|
269
|
+
"State Code" => l.state_code, "Country" => l.country,
|
270
|
+
"Country Code" => l.country_code, "Zip Code" => l.zip_code,
|
271
|
+
"Latitude" => l.latitude, "Longitude" => l.longitude })
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def pretty_station(s)
|
276
|
+
return unless s
|
277
|
+
section("STATION", 2) do
|
278
|
+
pretty_hash({
|
279
|
+
"ID" => s.id, "Name" => s.name,
|
280
|
+
"City" => s.city, "State Name" => s.state_name,
|
281
|
+
"State Code" => s.state_code, "Country" => s.country,
|
282
|
+
"Country Code" => s.country_code, "Zip Code" => s.zip_code,
|
283
|
+
"Latitude" => s.latitude, "Longitude" => s.longitude })
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def pretty_timezone(t)
|
288
|
+
return unless t
|
289
|
+
section("TIMEZONE", 2) do
|
290
|
+
pretty_hash({ "Long" => t.timezone, "Code" => t.code,"DST?" => t.dst? })
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def pretty_current(c)
|
295
|
+
return unless c
|
296
|
+
section("CURRENT", 2) do
|
297
|
+
pretty_hash({
|
298
|
+
"Time" => c.time, "Local Time" => c.local_time,
|
299
|
+
"Humidity" => c.humidity, "Icon" => c.icon,
|
300
|
+
"Condition" => c.condition, "Temperature" => c.temperature,
|
301
|
+
"Dew Point" => c.dew_point, "Heat Index" => c.heat_index,
|
302
|
+
"Pressure" => c.pressure, "Visibility" => c.visibility })
|
303
|
+
pretty_hash({ "Wind Chill" => c.wind_chill, "Wind" => c.wind,
|
304
|
+
"Wind Direction" => c.wind.direction, "Degrees" => c.wind.degrees }) if c.wind
|
305
|
+
pretty_hash({ "Sun Rise" => c.sun.rise, "Sun Set" => c.sun.set }) if c.sun
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def pretty_forecast(f)
|
310
|
+
return unless f
|
311
|
+
section("FOR: #{f.date}", 3) do
|
312
|
+
pretty_hash({
|
313
|
+
"Date" => f.date, "Icon" => f.icon,
|
314
|
+
"Condition" => f.condition, "High" => f.high,
|
315
|
+
"Low" => f.low, "POP" => f.pop })
|
316
|
+
pretty_hash({ "Sun Rise" => f.sun.rise, "Sun Set" => f.sun.set }) if f.sun
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
def pretty_forecasts(forecasts)
|
321
|
+
return unless forecasts
|
322
|
+
section("FORECAST", 3, false) do
|
323
|
+
blank
|
324
|
+
forecasts.each do |forecast|
|
325
|
+
pretty_forecast(forecast)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def pretty_measurement(m)
|
331
|
+
return unless m
|
332
|
+
section(m.source.to_s, 1) do
|
333
|
+
pretty_hash({
|
334
|
+
"Source" => m.source, "Time" => m.time,
|
335
|
+
"Metric" => m.metric?, "Success" => m.success? })
|
336
|
+
end
|
337
|
+
pretty_location(m.location)
|
338
|
+
pretty_station(m.station)
|
339
|
+
pretty_timezone(m.timezone)
|
340
|
+
pretty_current(m.current)
|
341
|
+
pretty_forecasts(m.forecast)
|
342
|
+
end
|
343
|
+
|
344
|
+
def pretty_measurements(w)
|
345
|
+
return unless w
|
346
|
+
section("MEASUREMENTS", 1) do
|
347
|
+
blank
|
348
|
+
w.measurements.each do |m|
|
349
|
+
pretty_measurement(m)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
def pretty_info
|
355
|
+
title("INFO", 1)
|
356
|
+
value("GitHub", "http://github.com/attack/barometer")
|
357
|
+
end
|
358
|
+
|
359
|
+
def pretty_output(barometer)
|
360
|
+
weather = barometer.weather
|
361
|
+
if weather
|
362
|
+
div
|
363
|
+
puts "#"
|
364
|
+
puts "# #{weather.default.location.name || barometer.query.q}"
|
365
|
+
puts "#"
|
366
|
+
div
|
367
|
+
blank
|
368
|
+
pretty_summary(weather)
|
369
|
+
pretty_query(barometer.query)
|
370
|
+
pretty_measurements(weather)
|
371
|
+
pretty_info
|
372
|
+
div("-")
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def run_web_mode(query=nil)
|
377
|
+
|
378
|
+
raise "This is currently disabled"
|
379
|
+
|
380
|
+
#require File.expand_path(File.dirname(__FILE__) + '/../lib/webometer/webometer.rb')
|
381
|
+
#require 'vegas'
|
382
|
+
|
383
|
+
#Vegas::Runner.new(Webometer, 'webometer') do |opts, app|
|
384
|
+
# opts is an option parser object
|
385
|
+
# app is your app class
|
386
|
+
#end
|
387
|
+
end
|
388
|
+
|
389
|
+
def geocode_google_key_message
|
58
390
|
puts
|
391
|
+
puts "Please update the key_file '#{KEY_FILE}' with your google api key"
|
392
|
+
puts "Get it here: http://code.google.com/apis/maps/signup.html"
|
393
|
+
puts "The, add this line to the file:"
|
394
|
+
puts "geocode_google: YOUR_KEY_KERE"
|
59
395
|
puts
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
396
|
+
end
|
397
|
+
|
398
|
+
# set API keys
|
399
|
+
if File.exists?(KEY_FILE)
|
400
|
+
keys = YAML.load_file(KEY_FILE)
|
401
|
+
if keys["geocode_google"]
|
402
|
+
Barometer.google_geocode_key = keys["geocode_google"]
|
403
|
+
else
|
404
|
+
geocode_google_key_message
|
405
|
+
exit
|
406
|
+
end
|
407
|
+
else
|
408
|
+
File.open(KEY_FILE, 'w') {|f| f << "geocode_google: YOUR_KEY_KERE" }
|
409
|
+
geocode_google_key_message
|
410
|
+
exit
|
411
|
+
end
|
412
|
+
|
413
|
+
# Create and run the application
|
414
|
+
app = App.new(ARGV, STDIN)
|
415
|
+
app.run
|