barometer 0.3.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +78 -70
- data/VERSION.yml +2 -2
- data/bin/barometer +100 -37
- data/lib/barometer.rb +12 -8
- data/lib/barometer/base.rb +48 -20
- data/lib/barometer/data.rb +5 -1
- data/lib/barometer/data/current.rb +23 -15
- data/lib/barometer/data/distance.rb +15 -5
- data/lib/barometer/data/forecast.rb +23 -5
- data/lib/barometer/data/geo.rb +16 -54
- data/lib/barometer/data/local_datetime.rb +137 -0
- data/lib/barometer/data/local_time.rb +134 -0
- data/lib/barometer/data/location.rb +6 -1
- data/lib/barometer/data/measurement.rb +71 -42
- data/lib/barometer/data/night.rb +69 -0
- data/lib/barometer/data/pressure.rb +15 -5
- data/lib/barometer/data/speed.rb +16 -5
- data/lib/barometer/data/sun.rb +8 -20
- data/lib/barometer/data/temperature.rb +22 -9
- data/lib/barometer/data/units.rb +10 -19
- data/lib/barometer/data/zone.rb +135 -9
- data/lib/barometer/formats.rb +12 -0
- data/lib/barometer/formats/coordinates.rb +42 -0
- data/lib/barometer/formats/format.rb +46 -0
- data/lib/barometer/formats/geocode.rb +51 -0
- data/lib/barometer/formats/icao.rb +37 -0
- data/lib/barometer/formats/postalcode.rb +22 -0
- data/lib/barometer/formats/short_zipcode.rb +17 -0
- data/lib/barometer/formats/weather_id.rb +107 -0
- data/lib/barometer/formats/zipcode.rb +31 -0
- data/lib/barometer/query.rb +61 -232
- data/lib/barometer/services.rb +14 -4
- data/lib/barometer/translations/icao_country_codes.yml +9 -0
- data/lib/barometer/translations/weather_country_codes.yml +17 -0
- data/lib/barometer/weather.rb +51 -30
- data/lib/barometer/{services → weather_services}/google.rb +23 -26
- data/lib/barometer/weather_services/noaa.rb +6 -0
- data/lib/barometer/{services → weather_services}/service.rb +101 -92
- data/lib/barometer/weather_services/weather_bug.rb +6 -0
- data/lib/barometer/weather_services/weather_dot_com.rb +261 -0
- data/lib/barometer/{services → weather_services}/wunderground.rb +58 -76
- data/lib/barometer/{services → weather_services}/yahoo.rb +91 -121
- data/lib/barometer/web_services/geocode.rb +33 -0
- data/lib/barometer/web_services/weather_id.rb +37 -0
- data/lib/barometer/web_services/web_service.rb +32 -0
- data/lib/demometer/demometer.rb +31 -4
- data/lib/demometer/views/forecast.erb +20 -0
- data/lib/demometer/views/index.erb +10 -3
- data/lib/demometer/views/measurement.erb +8 -3
- data/lib/demometer/views/readme.erb +63 -24
- data/spec/barometer_spec.rb +18 -36
- data/spec/{data_current_spec.rb → data/current_spec.rb} +73 -49
- data/spec/{data_distance_spec.rb → data/distance_spec.rb} +30 -30
- data/spec/{data_forecast_spec.rb → data/forecast_spec.rb} +57 -15
- data/spec/data/geo_spec.rb +91 -0
- data/spec/data/local_datetime_spec.rb +269 -0
- data/spec/data/local_time_spec.rb +239 -0
- data/spec/{data_location_spec.rb → data/location_spec.rb} +12 -1
- data/spec/{data_measurement_spec.rb → data/measurement_spec.rb} +135 -66
- data/spec/data/night_measurement_spec.rb +136 -0
- data/spec/{data_pressure_spec.rb → data/pressure_spec.rb} +29 -29
- data/spec/{data_speed_spec.rb → data/speed_spec.rb} +30 -30
- data/spec/data/sun_spec.rb +49 -0
- data/spec/{data_temperature_spec.rb → data/temperature_spec.rb} +44 -44
- data/spec/{units_spec.rb → data/units_spec.rb} +6 -6
- data/spec/{data_zone_spec.rb → data/zone_spec.rb} +15 -15
- data/spec/fixtures/formats/weather_id/90210.xml +1 -0
- data/spec/fixtures/formats/weather_id/atlanta.xml +1 -0
- data/spec/fixtures/formats/weather_id/from_USGA0028.xml +1 -0
- data/spec/fixtures/formats/weather_id/new_york.xml +1 -0
- data/spec/fixtures/{geocode_40_73.xml → geocode/40_73.xml} +0 -0
- data/spec/fixtures/{geocode_90210.xml → geocode/90210.xml} +0 -0
- data/spec/fixtures/{geocode_T5B4M9.xml → geocode/T5B4M9.xml} +0 -0
- data/spec/fixtures/geocode/atlanta.xml +1 -0
- data/spec/fixtures/{geocode_calgary_ab.xml → geocode/calgary_ab.xml} +0 -0
- data/spec/fixtures/{geocode_ksfo.xml → geocode/ksfo.xml} +0 -0
- data/spec/fixtures/{geocode_newyork_ny.xml → geocode/newyork_ny.xml} +0 -0
- data/spec/fixtures/{google_calgary_ab.xml → services/google/calgary_ab.xml} +0 -0
- data/spec/fixtures/services/weather_dot_com/90210.xml +1 -0
- data/spec/fixtures/{current_calgary_ab.xml → services/wunderground/current_calgary_ab.xml} +0 -0
- data/spec/fixtures/{forecast_calgary_ab.xml → services/wunderground/forecast_calgary_ab.xml} +0 -0
- data/spec/fixtures/{yahoo_90210.xml → services/yahoo/90210.xml} +0 -0
- data/spec/formats/coordinates_spec.rb +158 -0
- data/spec/formats/format_spec.rb +73 -0
- data/spec/formats/geocode_spec.rb +179 -0
- data/spec/formats/icao_spec.rb +61 -0
- data/spec/formats/postalcode_spec.rb +59 -0
- data/spec/formats/short_zipcode_spec.rb +53 -0
- data/spec/formats/weather_id_spec.rb +191 -0
- data/spec/formats/zipcode_spec.rb +111 -0
- data/spec/query_spec.rb +261 -288
- data/spec/spec_helper.rb +128 -4
- data/spec/{service_google_spec.rb → weather_services/google_spec.rb} +46 -46
- data/spec/weather_services/services_spec.rb +1118 -0
- data/spec/weather_services/weather_dot_com_spec.rb +327 -0
- data/spec/weather_services/wunderground_spec.rb +332 -0
- data/spec/{service_yahoo_spec.rb → weather_services/yahoo_spec.rb} +65 -81
- data/spec/weather_spec.rb +73 -61
- data/spec/web_services/geocode_spec.rb +45 -0
- data/spec/web_services/web_services_spec.rb +26 -0
- metadata +88 -36
- data/lib/barometer/services/noaa.rb +0 -6
- data/lib/barometer/services/weather_bug.rb +0 -6
- data/lib/barometer/services/weather_dot_com.rb +0 -6
- data/spec/data_geo_spec.rb +0 -94
- data/spec/data_sun_spec.rb +0 -76
- data/spec/service_wunderground_spec.rb +0 -330
- data/spec/services_spec.rb +0 -1106
@@ -1,6 +1,6 @@
|
|
1
1
|
module Barometer
|
2
2
|
#
|
3
|
-
# = Yahoo Weather
|
3
|
+
# = Yahoo! Weather
|
4
4
|
# www.yahoo.com
|
5
5
|
#
|
6
6
|
# - key required: NO
|
@@ -15,8 +15,6 @@ module Barometer
|
|
15
15
|
# - sun rise/set: YES (today only)
|
16
16
|
# - provides timezone: PARTIAL (just short code)
|
17
17
|
# - requires TZInfo: NO
|
18
|
-
# NOTE: since this only supports US, the short code can be used
|
19
|
-
# to convert times (until yahoo location id support is added)
|
20
18
|
#
|
21
19
|
# == resources
|
22
20
|
# - API: http://developer.yahoo.com/weather/
|
@@ -28,22 +26,27 @@ module Barometer
|
|
28
26
|
#
|
29
27
|
# where query can be:
|
30
28
|
# - zipcode (US)
|
31
|
-
# - Yahoo Location ID (International)
|
29
|
+
# - Yahoo! Location ID [actually weather.com id] (International)
|
30
|
+
#
|
31
|
+
# = Yahoo! terms of use
|
32
|
+
# The feeds are provided free of charge for use by individuals and non-profit
|
33
|
+
# organizations for personal, non-commercial uses. We ask that you provide
|
34
|
+
# attribution to Yahoo! Weather in connection with your use of the feeds.
|
35
|
+
# If you provide this attribution in text, please use: "Yahoo! Weather." If you
|
36
|
+
# provide this attribution with a graphic, please use the Yahoo! Weather logo that
|
37
|
+
# we have included in the feed itself.
|
38
|
+
# We reserve all rights in and to the Yahoo! Weather logo, and your right to use
|
39
|
+
# the Yahoo! Weather logo is limited to providing attribution in connection with
|
40
|
+
# these RSS feeds. Yahoo! also reserves the right to require you to cease
|
41
|
+
# distributing these feeds at any time for any reason.
|
32
42
|
#
|
33
43
|
# == notes
|
34
|
-
# - the Yahoo Location ID is a propreitary number (
|
35
|
-
# so this driver currently does not provide a way to get/use this number,
|
36
|
-
# therefore International support is currently missing
|
44
|
+
# - the Yahoo! Location ID is a propreitary number (shared with weather.com)
|
37
45
|
#
|
38
|
-
class Yahoo <
|
39
|
-
|
40
|
-
def self.accepted_formats
|
41
|
-
[:zipcode]
|
42
|
-
end
|
46
|
+
class WeatherService::Yahoo < WeatherService
|
43
47
|
|
44
|
-
def self.source_name
|
45
|
-
|
46
|
-
end
|
48
|
+
def self.source_name; :yahoo; end
|
49
|
+
def self.accepted_formats; [:zipcode, :weather_id]; end
|
47
50
|
|
48
51
|
# these are the icon codes that indicate "wet", used by wet? function
|
49
52
|
def self.wet_icon_codes
|
@@ -54,19 +57,14 @@ module Barometer
|
|
54
57
|
codes = (29..34).to_a + [36]
|
55
58
|
codes.collect {|c| c.to_s}
|
56
59
|
end
|
57
|
-
|
58
|
-
# override, only currently supports US
|
59
|
-
def self.supports_country?(query=nil)
|
60
|
-
query && query.country_code && query.country_code.downcase == "us"
|
61
|
-
end
|
62
60
|
|
63
61
|
def self._measure(measurement, query, metric=true)
|
64
|
-
raise ArgumentError unless measurement.is_a?(
|
62
|
+
raise ArgumentError unless measurement.is_a?(Data::Measurement)
|
65
63
|
raise ArgumentError unless query.is_a?(Barometer::Query)
|
66
64
|
measurement.source = self.source_name
|
67
65
|
|
68
66
|
begin
|
69
|
-
result = self.
|
67
|
+
result = self.fetch(query.q, metric)
|
70
68
|
rescue Timeout::Error => e
|
71
69
|
return measurement
|
72
70
|
end
|
@@ -75,7 +73,10 @@ module Barometer
|
|
75
73
|
measurement.forecast = self.build_forecast(result, metric)
|
76
74
|
measurement.location = self.build_location(result, query.geo)
|
77
75
|
|
78
|
-
|
76
|
+
if result["title"] && result["link"]
|
77
|
+
measurement.links[result["title"]] = result["link"]
|
78
|
+
end
|
79
|
+
|
79
80
|
sun = nil
|
80
81
|
if measurement.current
|
81
82
|
sun = self.build_sun(result)
|
@@ -83,42 +84,87 @@ module Barometer
|
|
83
84
|
end
|
84
85
|
# use todays sun data for all future days
|
85
86
|
if measurement.forecast && sun
|
86
|
-
start_date = Date.parse(measurement.current.local_time)
|
87
87
|
measurement.forecast.each do |forecast|
|
88
|
-
|
89
|
-
forecast.sun = Barometer::Sun.add_days!(sun,days_in_future.to_i)
|
88
|
+
forecast.sun = sun
|
90
89
|
end
|
91
90
|
end
|
92
91
|
|
92
|
+
local_time = self.build_local_time(result)
|
93
|
+
if local_time
|
94
|
+
measurement.measured_at = local_time
|
95
|
+
measurement.current.current_at = local_time
|
96
|
+
end
|
97
|
+
|
93
98
|
measurement
|
94
99
|
end
|
95
100
|
|
101
|
+
def self.build_local_time(data)
|
102
|
+
if data
|
103
|
+
if data['item']
|
104
|
+
# what time is it now?
|
105
|
+
now_utc = Time.now.utc
|
106
|
+
|
107
|
+
# get published date
|
108
|
+
pub_date = data['item']['pubDate']
|
109
|
+
|
110
|
+
# get the TIME ZONE CODE
|
111
|
+
zone_match = pub_date.match(/ ([A-Z]*)$/) if pub_date
|
112
|
+
|
113
|
+
if zone_match
|
114
|
+
zone = zone_match[1]
|
115
|
+
|
116
|
+
# try converting pub_date to utc
|
117
|
+
# pub_date_utc = Data::Zone.code_to_utc(Time.parse(pub_date), zone) if zone
|
118
|
+
|
119
|
+
# how far back was this?
|
120
|
+
# data_age_in_seconds = now_utc - pub_date_utc
|
121
|
+
|
122
|
+
# is this older then 2 hours
|
123
|
+
# if (data_age_in_seconds < 0) || (data_age_in_seconds > (60 * 60 * 2))
|
124
|
+
# we may have converted the time wrong.
|
125
|
+
# if pub_date in the future, then?
|
126
|
+
# if pub_date too far back, then?
|
127
|
+
|
128
|
+
# for now do nothing ... don't set measured_time
|
129
|
+
# return nil
|
130
|
+
# else
|
131
|
+
# everything seems fine
|
132
|
+
# convert now to the local time
|
133
|
+
offset = Data::Zone.zone_to_offset(zone)
|
134
|
+
return Data::LocalTime.parse(now_utc + offset)
|
135
|
+
# end
|
136
|
+
end
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
96
142
|
def self.build_current(data, metric=true)
|
97
143
|
raise ArgumentError unless data.is_a?(Hash)
|
98
|
-
current = CurrentMeasurement.new
|
144
|
+
current = Data::CurrentMeasurement.new
|
99
145
|
if data
|
100
146
|
if data['item'] && data['item']['yweather:condition']
|
101
147
|
condition_result = data['item']['yweather:condition']
|
102
|
-
current.
|
148
|
+
current.updated_at = Data::LocalDateTime.parse(condition_result['date'])
|
103
149
|
current.icon = condition_result['code']
|
104
150
|
current.condition = condition_result['text']
|
105
|
-
current.temperature = Temperature.new(metric)
|
151
|
+
current.temperature = Data::Temperature.new(metric)
|
106
152
|
current.temperature << condition_result['temp']
|
107
153
|
end
|
108
154
|
if data['yweather:atmosphere']
|
109
155
|
atmosphere_result = data['yweather:atmosphere']
|
110
156
|
current.humidity = atmosphere_result['humidity'].to_i
|
111
|
-
current.pressure = Pressure.new(metric)
|
157
|
+
current.pressure = Data::Pressure.new(metric)
|
112
158
|
current.pressure << atmosphere_result['pressure']
|
113
|
-
current.visibility = Distance.new(metric)
|
159
|
+
current.visibility = Data::Distance.new(metric)
|
114
160
|
current.visibility << atmosphere_result['visibility']
|
115
161
|
end
|
116
162
|
if data['yweather:wind']
|
117
163
|
wind_result = data['yweather:wind']
|
118
|
-
current.wind = Speed.new(metric)
|
164
|
+
current.wind = Data::Speed.new(metric)
|
119
165
|
current.wind << wind_result['speed']
|
120
166
|
current.wind.degrees = wind_result['degrees'].to_f
|
121
|
-
current.wind_chill = Temperature.new(metric)
|
167
|
+
current.wind_chill = Data::Temperature.new(metric)
|
122
168
|
current.wind_chill << wind_result['chill']
|
123
169
|
end
|
124
170
|
end
|
@@ -133,13 +179,13 @@ module Barometer
|
|
133
179
|
forecast_result = data['item']['yweather:forecast']
|
134
180
|
|
135
181
|
forecast_result.each do |forecast|
|
136
|
-
forecast_measurement = ForecastMeasurement.new
|
182
|
+
forecast_measurement = Data::ForecastMeasurement.new
|
137
183
|
forecast_measurement.icon = forecast['code']
|
138
184
|
forecast_measurement.date = Date.parse(forecast['date'])
|
139
185
|
forecast_measurement.condition = forecast['text']
|
140
|
-
forecast_measurement.high = Temperature.new(metric)
|
186
|
+
forecast_measurement.high = Data::Temperature.new(metric)
|
141
187
|
forecast_measurement.high << forecast['high'].to_f
|
142
|
-
forecast_measurement.low = Temperature.new(metric)
|
188
|
+
forecast_measurement.low = Data::Temperature.new(metric)
|
143
189
|
forecast_measurement.low << forecast['low'].to_f
|
144
190
|
forecasts << forecast_measurement
|
145
191
|
end
|
@@ -149,8 +195,8 @@ module Barometer
|
|
149
195
|
|
150
196
|
def self.build_location(data, geo=nil)
|
151
197
|
raise ArgumentError unless data.is_a?(Hash)
|
152
|
-
raise ArgumentError unless (geo.nil? || geo.is_a?(
|
153
|
-
location = Location.new
|
198
|
+
raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
|
199
|
+
location = Data::Location.new
|
154
200
|
# use the geocoded data if available, otherwise get data from result
|
155
201
|
if geo
|
156
202
|
location.city = geo.locality
|
@@ -177,41 +223,16 @@ module Barometer
|
|
177
223
|
raise ArgumentError unless data.is_a?(Hash)
|
178
224
|
sun = nil
|
179
225
|
if data && data['yweather:astronomy'] && data['item']
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
# get the sun rise and set
|
184
|
-
rise = Barometer::Zone.merge(
|
185
|
-
data['yweather:astronomy']['sunrise'],
|
186
|
-
data['item']['pubDate'],
|
187
|
-
zone
|
188
|
-
)
|
189
|
-
set = Barometer::Zone.merge(
|
190
|
-
data['yweather:astronomy']['sunset'],
|
191
|
-
data['item']['pubDate'],
|
192
|
-
zone
|
193
|
-
)
|
194
|
-
sun = Sun.new(rise, set)
|
226
|
+
local_rise = Data::LocalTime.parse(data['yweather:astronomy']['sunrise'])
|
227
|
+
local_set = Data::LocalTime.parse(data['yweather:astronomy']['sunset'])
|
228
|
+
sun = Data::Sun.new(local_rise, local_set)
|
195
229
|
end
|
196
|
-
sun || Sun.new
|
230
|
+
sun || Data::Sun.new
|
197
231
|
end
|
198
232
|
|
199
|
-
# def self.build_timezone(data)
|
200
|
-
# raise ArgumentError unless data.is_a?(Hash)
|
201
|
-
#
|
202
|
-
# timezone = nil
|
203
|
-
# if data && data['simpleforecast'] &&
|
204
|
-
# data['simpleforecast']['forecastday'] &&
|
205
|
-
# data['simpleforecast']['forecastday'].first &&
|
206
|
-
# data['simpleforecast']['forecastday'].first['date']
|
207
|
-
# timezone = Barometer::Zone.new(Time.now.utc,data['simpleforecast']['forecastday'].first['date']['tz_long'])
|
208
|
-
# end
|
209
|
-
# timezone
|
210
|
-
# end
|
211
|
-
|
212
233
|
# use HTTParty to get the current weather
|
213
|
-
def self.
|
214
|
-
|
234
|
+
def self.fetch(query, metric=true)
|
235
|
+
self.get(
|
215
236
|
"http://weather.yahooapis.com/forecastrss",
|
216
237
|
:query => {:p => query, :u => (metric ? 'c' : 'f')},
|
217
238
|
:format => :xml,
|
@@ -220,55 +241,4 @@ module Barometer
|
|
220
241
|
end
|
221
242
|
|
222
243
|
end
|
223
|
-
end
|
224
|
-
|
225
|
-
# Condition Codes
|
226
|
-
# 0 tornado
|
227
|
-
# 1 tropical storm
|
228
|
-
# 2 hurricane
|
229
|
-
# 3 severe thunderstorms
|
230
|
-
# 4 thunderstorms
|
231
|
-
# 5 mixed rain and snow
|
232
|
-
# 6 mixed rain and sleet
|
233
|
-
# 7 mixed snow and sleet
|
234
|
-
# 8 freezing drizzle
|
235
|
-
# 9 drizzle
|
236
|
-
# 10 freezing rain
|
237
|
-
# 11 showers
|
238
|
-
# 12 showers
|
239
|
-
# 13 snow flurries
|
240
|
-
# 14 light snow showers
|
241
|
-
# 15 blowing snow
|
242
|
-
# 16 snow
|
243
|
-
# 17 hail
|
244
|
-
# 18 sleet
|
245
|
-
# 19 dust
|
246
|
-
# 20 foggy
|
247
|
-
# 21 haze
|
248
|
-
# 22 smoky
|
249
|
-
# 23 blustery
|
250
|
-
# 24 windy
|
251
|
-
# 25 cold
|
252
|
-
# 26 cloudy
|
253
|
-
# 27 mostly cloudy (night)
|
254
|
-
# 28 mostly cloudy (day)
|
255
|
-
# 29 partly cloudy (night)
|
256
|
-
# 30 partly cloudy (day)
|
257
|
-
# 31 clear (night)
|
258
|
-
# 32 sunny
|
259
|
-
# 33 fair (night)
|
260
|
-
# 34 fair (day)
|
261
|
-
# 35 mixed rain and hail
|
262
|
-
# 36 hot
|
263
|
-
# 37 isolated thunderstorms
|
264
|
-
# 38 scattered thunderstorms
|
265
|
-
# 39 scattered thunderstorms
|
266
|
-
# 40 scattered showers
|
267
|
-
# 41 heavy snow
|
268
|
-
# 42 scattered snow showers
|
269
|
-
# 43 heavy snow
|
270
|
-
# 44 partly cloudy
|
271
|
-
# 45 thundershowers
|
272
|
-
# 46 snow showers
|
273
|
-
# 47 isolated thundershowers
|
274
|
-
# 3200 not available
|
244
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Barometer
|
2
|
+
#
|
3
|
+
# Web Service: Geocode
|
4
|
+
#
|
5
|
+
# uses Google Maps Geocoding service
|
6
|
+
#
|
7
|
+
class WebService::Geocode < WebService
|
8
|
+
|
9
|
+
def self.fetch(query)
|
10
|
+
raise ArgumentError unless _is_a_query?(query)
|
11
|
+
return nil unless _has_geocode_key?
|
12
|
+
location = self.get(
|
13
|
+
"http://maps.google.com/maps/geo",
|
14
|
+
:query => {
|
15
|
+
:gl => query.country_code, :key => Barometer.google_geocode_key,
|
16
|
+
:output => "xml", :q => query.q
|
17
|
+
},
|
18
|
+
:format => :xml, :timeout => Barometer.timeout
|
19
|
+
)
|
20
|
+
location = location['kml']['Response'] if location && location['kml']
|
21
|
+
location ? (geo = Data::Geo.new(location)) : nil
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def self._has_geocode_key?
|
27
|
+
!Barometer.google_geocode_key.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Barometer
|
2
|
+
#
|
3
|
+
# Web Service: WeatherID
|
4
|
+
#
|
5
|
+
# uses Weather.com search to obtain a weather id
|
6
|
+
#
|
7
|
+
class WebService::WeatherID < WebService
|
8
|
+
|
9
|
+
# get the weather_id for a given query
|
10
|
+
#
|
11
|
+
def self.fetch(query)
|
12
|
+
return nil unless query
|
13
|
+
raise ArgumentError unless _is_a_query?(query)
|
14
|
+
response = self.get(
|
15
|
+
"http://xoap.weather.com/search/search",
|
16
|
+
:query => { :where => query.q }, :format => :plain,
|
17
|
+
:timeout => Barometer.timeout
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
# get the location_date (geocode) for a given weather_id
|
22
|
+
#
|
23
|
+
def self.reverse(query)
|
24
|
+
return nil unless query
|
25
|
+
raise ArgumentError unless _is_a_query?(query)
|
26
|
+
self.get(
|
27
|
+
"http://weather.yahooapis.com/forecastrss",
|
28
|
+
:query => { :p => query.q },
|
29
|
+
:format => :xml,
|
30
|
+
:timeout => Barometer.timeout
|
31
|
+
)['rss']['channel']["yweather:location"]
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'httparty'
|
3
|
+
|
4
|
+
$:.unshift(File.dirname(__FILE__))
|
5
|
+
require 'extensions/httparty'
|
6
|
+
|
7
|
+
module Barometer
|
8
|
+
#
|
9
|
+
# Web Service Class
|
10
|
+
#
|
11
|
+
# This is a base class for creating web service api-consuming
|
12
|
+
# drivers. Each driver inherits from this class.
|
13
|
+
#
|
14
|
+
# Basically, all a service is required to do is take a query
|
15
|
+
# (ie "Paris") and return it corresponding data class
|
16
|
+
#
|
17
|
+
class WebService
|
18
|
+
# all web_service drivers will use the HTTParty gem
|
19
|
+
include HTTParty
|
20
|
+
|
21
|
+
# STUB: define this method to actually retireve the data
|
22
|
+
def self.fetch(query=nil); raise NotImplementedError; end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def self._is_a_query?(object=nil)
|
27
|
+
return false unless object
|
28
|
+
object.is_a?(Barometer::Query)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/lib/demometer/demometer.rb
CHANGED
@@ -3,15 +3,35 @@ require 'sinatra'
|
|
3
3
|
require 'barometer'
|
4
4
|
|
5
5
|
# load API keys
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
@@config_file ||= File.expand_path(File.join('~', '.barometer'))
|
7
|
+
keys = YAML.load_file(@@config_file)
|
8
|
+
if keys["google"] && keys["google"]["geocode"]
|
9
|
+
Barometer.google_geocode_key = keys["google"]["geocode"]
|
9
10
|
else
|
11
|
+
raise RunTimeError "no geocoding keys"
|
10
12
|
exit
|
11
13
|
end
|
12
14
|
|
13
15
|
class Demometer < Sinatra::Default
|
14
16
|
|
17
|
+
def config_weather_dot_com
|
18
|
+
if File.exists?(@@config_file)
|
19
|
+
keys = YAML.load_file(@@config_file)
|
20
|
+
if keys["weather"] && keys["weather"]["partner"] && keys["weather"]["license"]
|
21
|
+
partner_key = keys["weather"]["partner"].to_s
|
22
|
+
license_key = keys["weather"]["license"].to_s
|
23
|
+
else
|
24
|
+
raise RunTimeError "no weather.com keys"
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
else
|
28
|
+
File.open(@@config_file, 'w') {|f| f << "\nweather:\n partner: PARTNER_KEY\n license: LICENSE_KEY" }
|
29
|
+
raise RunTimeError "no weather.com keys"
|
30
|
+
exit
|
31
|
+
end
|
32
|
+
{ :weather_dot_com => { :keys => { :partner => partner_key, :license => license_key } } }
|
33
|
+
end
|
34
|
+
|
15
35
|
helpers do
|
16
36
|
def data(title, value)
|
17
37
|
return if value.nil?
|
@@ -29,7 +49,14 @@ class Demometer < Sinatra::Default
|
|
29
49
|
metric = (params[:query][:metric].to_s == "1" ? true : false)
|
30
50
|
|
31
51
|
# determine sources
|
32
|
-
Barometer.
|
52
|
+
Barometer.config = { 1 => params[:query][:source].collect{|s| s.to_sym } }
|
53
|
+
|
54
|
+
# setup weather.com
|
55
|
+
if Barometer::Base.config && Barometer::Base.config[1] &&
|
56
|
+
Barometer::Base.config[1].include?(:weather_dot_com)
|
57
|
+
Barometer::Base.config[1].delete(:weather_dot_com)
|
58
|
+
Barometer::Base.config[1] << config_weather_dot_com
|
59
|
+
end
|
33
60
|
|
34
61
|
if params[:query] && !params[:query][:q].empty?
|
35
62
|
@barometer = Barometer.new(params[:query][:q])
|