barometer 0.3.2 → 0.5.0
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/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])
|