yahoo-weather 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ = YAHOO_WEATHER_20091021_1_0_1
2
+
3
+ * [shaper] update documentation to reflect reality and use suffix for
4
+ rdoc format.
5
+
6
+ * [shaper] move source repository to github.
7
+
8
+ * [shaper] use Hoe for Rakefile and gem management.
9
+
10
+ * [shaper] fix test warnings.
11
+
12
+ = 20061105
13
+
14
+ * [shaper] Initial version.
@@ -0,0 +1,88 @@
1
+ = yahoo-weather
2
+
3
+ == About
4
+
5
+ yahoo-weather provides an object-oriented interface to the Yahoo! Weather XML
6
+ RSS feed detailed at http://developer.yahoo.com/weather.
7
+
8
+ People care a lot about the weather, which sometimes seems ironic given that
9
+ they can just glance out the window, but we can all understand the fascination
10
+ with details and forecasting.
11
+
12
+ Log the weather information to your database! Graph it to your heart's
13
+ content! Write a widget that emails the weather to your cell phone every five
14
+ minutes with a link to your friend's PayPal account to deposit money if the
15
+ weather's sunny and you both bet that it would be rainy. And the fun doesn't
16
+ have to stop there.
17
+
18
+ The RubyForge project page is at http://rubyforge.org/projects/yahoo-weather.
19
+
20
+ Source code is at http://github.com/shaper/yahoo-weather.
21
+
22
+ == Installation
23
+
24
+
25
+ Install +rubygems+ if you don't already have it. See http://rubyforge.org/projects/rubygems/.
26
+
27
+ Then install the gem by executing:
28
+
29
+ % gem install yahoo-weather
30
+
31
+ == Usage
32
+
33
+ A simple example program under +examples/example.rb+ as:
34
+
35
+ require 'rubygems'
36
+ require 'yahoo-weather'
37
+
38
+ @client = YahooWeather::Client.new
39
+ response = @client.lookup_location('98103')
40
+
41
+ # straight text output
42
+ print <<edoc
43
+ #{response.title}
44
+ #{response.condition.temp} degrees
45
+ #{response.condition.text}
46
+ edoc
47
+
48
+ # sample html output
49
+ print <<edoc
50
+ <div>
51
+ <img src="#{response.image_url}"><br/>
52
+ #{response.condition.temp} degrees #{response.units.temperature}<br/>
53
+ #{response.condition.text}<br>
54
+ Forecast:<br/>
55
+ #{response.forecasts[0].day} - #{response.forecasts[0].text}. High: #{response.forecasts[0].high} Low: #{response.forecasts[0].low}<br/>
56
+ #{response.forecasts[1].day} - #{response.forecasts[1].text}. High: #{response.forecasts[1].high} Low: #{response.forecasts[1].low}<br/>
57
+ More information <a href="#{response.page_url}">here</a>.
58
+ </div>
59
+ edoc
60
+
61
+ Produces output as:
62
+
63
+ Conditions for Seattle, WA at 2:53 pm PST
64
+ 55 degrees F
65
+ Light Rain
66
+ <div>
67
+ <img src="http://us.i1.yimg.com/us.yimg.com/i/us/we/52/11.gif"><br/>
68
+ 55 degrees F<br/>
69
+ Light Rain<br>
70
+ Forecast:<br/>
71
+ Sun - Rain/Wind. High: 56 Low: 54<br/>
72
+ Mon - Heavy Rain/Wind. High: 60 Low: 54<br/>
73
+ More information <a href="http://us.rd.yahoo.com/dailynews/rss/weather/Seattle__WA/*http://xml.weather.yahoo.com/forecast/98103_f.html">here</a>.
74
+ </div>
75
+
76
+ There is a variety of detailed weather information in other attributes of the
77
+ YahooWeather::Response object.
78
+
79
+ == License
80
+
81
+ This library is provided via the GNU LGPL license at http://www.gnu.org/licenses/lgpl.html.
82
+
83
+ == Author
84
+
85
+ Copyright 2006 - 2009, Walter Korman <shaper@fatgoose.com>,
86
+ http://www.lemurware.com.
87
+
88
+ Thanks to Matthew Berk for inspiration and initial hack.
data/Rakefile CHANGED
@@ -1,49 +1,25 @@
1
1
  require 'rubygems'
2
- require 'rake'
3
- require 'rake/testtask'
4
- require 'rake/rdoctask'
5
- require 'rake/gempackagetask'
2
+ require 'hoe'
3
+ $:.unshift(File.dirname(__FILE__) + "/lib")
4
+ require 'yahoo-weather'
6
5
 
7
- spec = Gem::Specification.new do |s|
8
- s.name = 'yahoo-weather'
9
- s.version = '1.0.0'
10
- s.summary = 'A Ruby object-oriented interface to the Yahoo! Weather service.'
11
- s.author = 'Walter Korman'
12
- s.email = 'shaper@wgks.org'
13
- s.platform = Gem::Platform::RUBY
14
- s.rubyforge_project = 'yahoo-weather'
15
- s.has_rdoc = true
16
- s.extra_rdoc_files = [ 'README' ]
17
- s.rdoc_options << '--main' << 'README'
18
- s.test_files = Dir.glob('test/test_*.rb')
19
- s.files = Dir.glob("{examples,lib,test}/**/*") +
20
- [ 'AUTHORS', 'CHANGELOG', 'LICENSE', 'README', 'Rakefile', 'TODO' ]
21
- s.add_dependency("xml-simple", ">= 1.0.9")
22
- end
23
-
24
- desc 'Run tests'
25
- task :default => [ :test ]
26
-
27
- Rake::TestTask.new('test') do |t|
28
- t.libs << 'test'
29
- t.pattern = 'test/test_*.rb'
30
- t.verbose = true
31
- end
6
+ Hoe.spec('yahoo-weather') do |p|
7
+ self.version = YahooWeather::VERSION
8
+ self.rubyforge_name = 'yahoo-weather'
9
+ self.author = 'Walter Korman'
10
+ self.email = 'shaper@fatgoose.com'
11
+ self.extra_deps << [ 'xml-simple', '>= 1.0.9' ]
12
+ self.summary = 'A Ruby object-oriented interface to the Yahoo! Weather service.'
13
+ self.description = <<EDOC
14
+ The yahoo-weather rubygem provides a Ruby object-oriented interface to the
15
+ Yahoo! Weather service described in detail at:
32
16
 
33
- desc 'Generate RDoc'
34
- Rake::RDocTask.new :rdoc do |rd|
35
- rd.rdoc_dir = 'doc'
36
- rd.rdoc_files.add 'lib', 'README'
37
- rd.main = 'README'
17
+ http://developer.yahoo.com/weather
18
+ EDOC
19
+ self.url = 'http://rubyforge.org/projects/yahoo-weather'
20
+ self.changes = p.paragraphs_of('CHANGELOG.rdoc', 0..1).join("\n\n")
21
+ self.remote_rdoc_dir = '' # Release to root
22
+ self.readme_file = 'README.rdoc'
23
+ self.history_file = 'CHANGELOG.rdoc'
24
+ self.extra_rdoc_files = [ 'CHANGELOG.rdoc', 'README.rdoc' ]
38
25
  end
39
-
40
- desc 'Build Gem'
41
- Rake::GemPackageTask.new spec do |pkg|
42
- pkg.need_tar = true
43
- end
44
-
45
- desc 'Clean up'
46
- task :clean => [ :clobber_rdoc, :clobber_package ]
47
-
48
- desc 'Clean up'
49
- task :clobber => [ :clean ]
data/TODO CHANGED
@@ -1,5 +1,6 @@
1
- - include the yahoo! weather logo image in the response
2
-
3
- - raise a module-specific exception on failure cases rather than just a string
4
-
5
- - add weather code image url accessor for forecasts
1
+ * use nokogiri instead of xmlsimple.
2
+ * break classes out into one per file.
3
+ * update super ancient coding style.
4
+ * include the yahoo! weather logo image in the response
5
+ * raise a module-specific exception on failure cases rather than just a string
6
+ * add weather code image url accessor for forecasts
File without changes
@@ -1,301 +1,303 @@
1
- # yahoo-weather -- provides OO access to the Yahoo! Weather RSS XML feed
2
- # Copyright (C) 2006 Walter Korman <shaper@wgks.org>
3
- #
4
- # This library is free software; you can redistribute it and/or
5
- # modify it under the terms of the GNU Lesser General Public
6
- # License as published by the Free Software Foundation; either
7
- # version 2.1 of the License, or (at your option) any later version.
8
- #
9
- # This library is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
- # Lesser General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU Lesser General Public
15
- # License along with this library; if not, write to the Free Software
16
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
-
18
- require 'net/http'
19
- require 'pp'
20
- require 'time'
21
- require 'xmlsimple'
22
-
23
- module YahooWeather
24
-
25
- # Describes astronomy information for a particular location.
26
- class Astronomy
27
- # a Time object detailing the sunrise time for a location.
28
- attr_reader :sunrise
29
-
30
- # a Time object detailing the sunset time for a location.
31
- attr_reader :sunset
32
-
33
- def initialize (payload)
34
- @sunrise = YahooWeather._parse_time(payload['sunrise'])
35
- @sunset = YahooWeather._parse_time(payload['sunset'])
36
- end
37
- end
38
-
39
- # Describes a geographical location.
40
- class Location
41
- # the name of the city.
42
- attr_reader :city
43
-
44
- # the name of the country.
45
- attr_reader :country
46
-
47
- # the name of the region, such as a state.
48
- attr_reader :region
49
-
50
- def initialize (payload)
51
- @city = payload['city']
52
- @country = payload['country']
53
- @region = payload['region']
54
- end
55
- end
56
-
57
- # Describes the units of measure with which weather information is provided.
58
- class Units
59
- # the units in which temperature is measured, e.g. +F+ for +Fahrenheit+ or +C+ for +Celsius+.
60
- attr_reader :temperature
61
-
62
- # the units in which distance is measured, e.g. +mi+ for +miles+.
63
- attr_reader :distance
64
-
65
- # the units in which pressure is measured, e.g. +in+ for +inches+.
66
- attr_reader :pressure
67
-
68
- # the units in which speed is measured, e.g. +mph+ for <tt>miles per hour</tt>.
69
- attr_reader :speed
70
-
71
- def initialize (payload)
72
- @temperature = payload['temperature']
73
- @distance = payload['distance']
74
- @pressure = payload['pressure']
75
- @speed = payload['speed']
76
- end
77
- end
78
-
79
- # Describes the specific wind conditions at a location.
80
- class Wind
81
- # the temperature factoring in wind chill.
82
- attr_reader :chill
83
-
84
- # the direction of the wind in degrees.
85
- attr_reader :direction
86
-
87
- # the speed of the wind.
88
- attr_reader :speed
89
-
90
- def initialize (payload)
91
- @chill = payload['chill'].to_i
92
- @direction = payload['direction'].to_i
93
- @speed = payload['speed'].to_i
94
- end
95
- end
96
-
97
- # Describes the specific atmospheric conditions at a location.
98
- class Atmosphere
99
- # the humidity of the surroundings.
100
- attr_reader :humidity
101
-
102
- # the visibility level of the surroundings
103
- attr_reader :visibility
104
-
105
- # the pressure level of the surroundings.
106
- attr_reader :pressure
107
-
108
- # whether the air currents are rising.
109
- attr_reader :rising
110
-
111
- def initialize (payload)
112
- @humidity = payload['humidity'].to_i
113
- @visibility = payload['visibility'].to_i
114
- @pressure = payload['pressure'].to_f
115
- @rising = (payload['rising'] == "1")
116
- end
117
- end
118
-
119
- class Condition
120
- # the Yahoo! Weather condition code, as detailed at http://developer.yahoo.com/weather.
121
- attr_reader :code
122
-
123
- # the date and time associated with these conditions.
124
- attr_reader :date
125
-
126
- # the temperature of the location.
127
- attr_reader :temp
128
-
129
- # the brief prose text description of the weather conditions of the location.
130
- attr_reader :text
131
-
132
- def initialize (payload)
133
- @code = payload['code'].to_i
134
- @date = YahooWeather._parse_time(payload['date'])
135
- @temp = payload['temp'].to_i
136
- @text = payload['text']
137
- end
138
- end
139
-
140
- # The forecasted weather conditions for a specific location.
141
- class Forecast
142
- # the brief name of the day associated with the forecast.
143
- attr_reader :day
144
-
145
- # the date associated with the forecast.
146
- attr_reader :date
147
-
148
- # the low temperature forecasted.
149
- attr_reader :low
150
-
151
- # the high temperature forecasted.
152
- attr_reader :high
153
-
154
- # the brief prose text description of the forecasted weather conditions.
155
- attr_reader :text
156
-
157
- # the Yahoo! Weather code associated with the forecast, per http://developer.yahoo.com/weather.
158
- attr_reader :code
159
-
160
- def initialize (payload)
161
- @day = payload['day']
162
- @date = YahooWeather._parse_time(payload['date'])
163
- @low = payload['low'].to_i
164
- @high = payload['high'].to_i
165
- @text = payload['text']
166
- @code = payload['code'].to_i
167
- end
168
- end
169
-
170
- # Describes the weather conditions for a particular requested location.
171
- class Response
172
- # a YahooWeather::Astronomy object detailing the sunrise and sunset
173
- # information for the requested location.
174
- attr_reader :astronomy
175
-
176
- # a YahooWeather::Location object detailing the precise geographical names
177
- # to which the requested location was mapped.
178
- attr_reader :location
179
-
180
- # a YahooWeather::Units object detailing the units corresponding to the
181
- # information detailed in the response.
182
- attr_reader :units
183
-
184
- # a YahooWeather::Wind object detailing the wind information at the
185
- # requested location.
186
- attr_reader :wind
187
-
188
- # a YahooWeather::Atmosphere object detailing the atmosphere information
189
- # of the requested location.
190
- attr_reader :atmosphere
191
-
192
- # a YahooWeather::Condition object detailing the current conditions of the
193
- # requested location.
194
- attr_reader :condition
195
-
196
- # a list of YahooWeather::Forecast objects detailing the high-level
197
- # forecasted weather conditions for upcoming days.
198
- attr_reader :forecasts
199
-
200
- # the raw HTML generated by the Yahoo! Weather service summarizing current
201
- # weather conditions for the requested location.
202
- attr_reader :description
203
-
204
- # a link to the Yahoo! Weather image icon representing the current weather
205
- # conditions visually.
206
- attr_reader :image_url
207
-
208
- # the latitude of the location for which weather is detailed.
209
- attr_reader :latitude
210
-
211
- # the longitude of the location for which weather is detailed.
212
- attr_reader :longitude
213
-
214
- # a link to the Yahoo! Weather page with full detailed information on the
215
- # requested location's current weather conditions.
216
- attr_reader :page_url
217
-
218
- # the location string initially requested of the service.
219
- attr_reader :request_location
220
-
221
- # the url with which the Yahoo! Weather service was accessed to build the response.
222
- attr_reader :request_url
223
-
224
- # the prose descriptive title of the weather information.
225
- attr_reader :title
226
-
227
- # regular expression used to pull the weather image icon from full
228
- # description text.
229
- @@REGEXP_IMAGE = Regexp.new(/img src="([^"]+)"/)
230
-
231
- def initialize (request_location, request_url, payload)
232
- @request_location = request_location
233
- @request_url = request_url
234
-
235
- root = payload['channel'].first
236
- @astronomy = YahooWeather::Astronomy.new root['astronomy'].first
237
- @location = YahooWeather::Location.new root['location'].first
238
- @units = YahooWeather::Units.new root['units'].first
239
- @wind = YahooWeather::Wind.new root['wind'].first
240
- @atmosphere = YahooWeather::Atmosphere.new root['atmosphere'].first
241
-
242
- item = root['item'].first
243
- @condition = YahooWeather::Condition.new item['condition'].first
244
- @forecasts = []
245
- item['forecast'].each { |forecast| @forecasts << YahooWeather::Forecast.new(forecast) }
246
- @latitude = item['lat'].first.to_f
247
- @longitude = item['long'].first.to_f
248
- @page_url = item['link'].first
249
- @title = item['title'].first
250
- @description = item['description'].first
251
-
252
- match_data = @@REGEXP_IMAGE.match(description)
253
- @image_url = (match_data) ? match_data[1] : nil
254
- end
255
- end
256
-
257
- # The main client object through which the Yahoo! Weather service may be accessed.
258
- class Client
259
- # the url with which we obtain weather information from yahoo
260
- @@API_URL = "http://xml.weather.yahoo.com/forecastrss"
261
-
262
- def initialize (api_url = @@API_URL)
263
- @api_url = api_url
264
- end
265
-
266
- # Returns a YahooWeather::Response object detailing the current weather
267
- # information for the specified location.
268
- #
269
- # +location+ can be either a US zip code or a location code. Location
270
- # codes can be looked up at http://weather.yahoo.com, where it will appear
271
- # in the URL that results from searching on the city or zip code. For
272
- # instance, searching on 'Seattle, WA' results in a URL ending in
273
- # 'USWA0395.html', so the location code for Seattle is 'USWA0395'.
274
- #
275
- # +units+ allows specifying whether to retrieve information in
276
- # +Fahrenheit+ as +f+, or +Celsius+ as +c+, and defaults to +f+.
277
- def lookup_location (location, units = 'f')
278
- # query the service to grab the xml data
279
- url = _request_url(location, units)
280
- begin
281
- response = Net::HTTP.get_response(URI.parse(url)).body.to_s
282
- rescue
283
- raise "failed to get weather via '#{url}': " + $!
284
- end
285
-
286
- # create the response object
287
- response = XmlSimple.xml_in(response)
288
- YahooWeather::Response.new(location, url, response)
289
- end
290
-
291
- private
292
- def _request_url (location, units)
293
- @api_url + '?p=' + URI.encode(location) + '&u=' + URI.encode(units)
294
- end
295
- end
296
-
297
- private
298
- def self._parse_time (text)
299
- (text) ? Time.parse(text) : nil
300
- end
301
- end
1
+ # yahoo-weather -- provides OO access to the Yahoo! Weather RSS XML feed
2
+ # Copyright (C) 2006 Walter Korman <shaper@wgks.org>
3
+ #
4
+ # This library is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU Lesser General Public
6
+ # License as published by the Free Software Foundation; either
7
+ # version 2.1 of the License, or (at your option) any later version.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+
18
+ require 'net/http'
19
+ require 'pp'
20
+ require 'time'
21
+ require 'xmlsimple'
22
+
23
+ class YahooWeather
24
+
25
+ VERSION = '1.0.1'
26
+
27
+ # Describes astronomy information for a particular location.
28
+ class Astronomy
29
+ # a Time object detailing the sunrise time for a location.
30
+ attr_reader :sunrise
31
+
32
+ # a Time object detailing the sunset time for a location.
33
+ attr_reader :sunset
34
+
35
+ def initialize (payload)
36
+ @sunrise = YahooWeather._parse_time(payload['sunrise'])
37
+ @sunset = YahooWeather._parse_time(payload['sunset'])
38
+ end
39
+ end
40
+
41
+ # Describes a geographical location.
42
+ class Location
43
+ # the name of the city.
44
+ attr_reader :city
45
+
46
+ # the name of the country.
47
+ attr_reader :country
48
+
49
+ # the name of the region, such as a state.
50
+ attr_reader :region
51
+
52
+ def initialize (payload)
53
+ @city = payload['city']
54
+ @country = payload['country']
55
+ @region = payload['region']
56
+ end
57
+ end
58
+
59
+ # Describes the units of measure with which weather information is provided.
60
+ class Units
61
+ # the units in which temperature is measured, e.g. +F+ for +Fahrenheit+ or +C+ for +Celsius+.
62
+ attr_reader :temperature
63
+
64
+ # the units in which distance is measured, e.g. +mi+ for +miles+.
65
+ attr_reader :distance
66
+
67
+ # the units in which pressure is measured, e.g. +in+ for +inches+.
68
+ attr_reader :pressure
69
+
70
+ # the units in which speed is measured, e.g. +mph+ for <tt>miles per hour</tt>.
71
+ attr_reader :speed
72
+
73
+ def initialize (payload)
74
+ @temperature = payload['temperature']
75
+ @distance = payload['distance']
76
+ @pressure = payload['pressure']
77
+ @speed = payload['speed']
78
+ end
79
+ end
80
+
81
+ # Describes the specific wind conditions at a location.
82
+ class Wind
83
+ # the temperature factoring in wind chill.
84
+ attr_reader :chill
85
+
86
+ # the direction of the wind in degrees.
87
+ attr_reader :direction
88
+
89
+ # the speed of the wind.
90
+ attr_reader :speed
91
+
92
+ def initialize (payload)
93
+ @chill = payload['chill'].to_i
94
+ @direction = payload['direction'].to_i
95
+ @speed = payload['speed'].to_i
96
+ end
97
+ end
98
+
99
+ # Describes the specific atmospheric conditions at a location.
100
+ class Atmosphere
101
+ # the humidity of the surroundings.
102
+ attr_reader :humidity
103
+
104
+ # the visibility level of the surroundings
105
+ attr_reader :visibility
106
+
107
+ # the pressure level of the surroundings.
108
+ attr_reader :pressure
109
+
110
+ # whether the air currents are rising.
111
+ attr_reader :rising
112
+
113
+ def initialize (payload)
114
+ @humidity = payload['humidity'].to_i
115
+ @visibility = payload['visibility'].to_i
116
+ @pressure = payload['pressure'].to_f
117
+ @rising = (payload['rising'] == "1")
118
+ end
119
+ end
120
+
121
+ class Condition
122
+ # the Yahoo! Weather condition code, as detailed at http://developer.yahoo.com/weather.
123
+ attr_reader :code
124
+
125
+ # the date and time associated with these conditions.
126
+ attr_reader :date
127
+
128
+ # the temperature of the location.
129
+ attr_reader :temp
130
+
131
+ # the brief prose text description of the weather conditions of the location.
132
+ attr_reader :text
133
+
134
+ def initialize (payload)
135
+ @code = payload['code'].to_i
136
+ @date = YahooWeather._parse_time(payload['date'])
137
+ @temp = payload['temp'].to_i
138
+ @text = payload['text']
139
+ end
140
+ end
141
+
142
+ # The forecasted weather conditions for a specific location.
143
+ class Forecast
144
+ # the brief name of the day associated with the forecast.
145
+ attr_reader :day
146
+
147
+ # the date associated with the forecast.
148
+ attr_reader :date
149
+
150
+ # the low temperature forecasted.
151
+ attr_reader :low
152
+
153
+ # the high temperature forecasted.
154
+ attr_reader :high
155
+
156
+ # the brief prose text description of the forecasted weather conditions.
157
+ attr_reader :text
158
+
159
+ # the Yahoo! Weather code associated with the forecast, per http://developer.yahoo.com/weather.
160
+ attr_reader :code
161
+
162
+ def initialize (payload)
163
+ @day = payload['day']
164
+ @date = YahooWeather._parse_time(payload['date'])
165
+ @low = payload['low'].to_i
166
+ @high = payload['high'].to_i
167
+ @text = payload['text']
168
+ @code = payload['code'].to_i
169
+ end
170
+ end
171
+
172
+ # Describes the weather conditions for a particular requested location.
173
+ class Response
174
+ # a YahooWeather::Astronomy object detailing the sunrise and sunset
175
+ # information for the requested location.
176
+ attr_reader :astronomy
177
+
178
+ # a YahooWeather::Location object detailing the precise geographical names
179
+ # to which the requested location was mapped.
180
+ attr_reader :location
181
+
182
+ # a YahooWeather::Units object detailing the units corresponding to the
183
+ # information detailed in the response.
184
+ attr_reader :units
185
+
186
+ # a YahooWeather::Wind object detailing the wind information at the
187
+ # requested location.
188
+ attr_reader :wind
189
+
190
+ # a YahooWeather::Atmosphere object detailing the atmosphere information
191
+ # of the requested location.
192
+ attr_reader :atmosphere
193
+
194
+ # a YahooWeather::Condition object detailing the current conditions of the
195
+ # requested location.
196
+ attr_reader :condition
197
+
198
+ # a list of YahooWeather::Forecast objects detailing the high-level
199
+ # forecasted weather conditions for upcoming days.
200
+ attr_reader :forecasts
201
+
202
+ # the raw HTML generated by the Yahoo! Weather service summarizing current
203
+ # weather conditions for the requested location.
204
+ attr_reader :description
205
+
206
+ # a link to the Yahoo! Weather image icon representing the current weather
207
+ # conditions visually.
208
+ attr_reader :image_url
209
+
210
+ # the latitude of the location for which weather is detailed.
211
+ attr_reader :latitude
212
+
213
+ # the longitude of the location for which weather is detailed.
214
+ attr_reader :longitude
215
+
216
+ # a link to the Yahoo! Weather page with full detailed information on the
217
+ # requested location's current weather conditions.
218
+ attr_reader :page_url
219
+
220
+ # the location string initially requested of the service.
221
+ attr_reader :request_location
222
+
223
+ # the url with which the Yahoo! Weather service was accessed to build the response.
224
+ attr_reader :request_url
225
+
226
+ # the prose descriptive title of the weather information.
227
+ attr_reader :title
228
+
229
+ # regular expression used to pull the weather image icon from full
230
+ # description text.
231
+ @@REGEXP_IMAGE = Regexp.new(/img src="([^"]+)"/)
232
+
233
+ def initialize (request_location, request_url, payload)
234
+ @request_location = request_location
235
+ @request_url = request_url
236
+
237
+ root = payload['channel'].first
238
+ @astronomy = YahooWeather::Astronomy.new root['astronomy'].first
239
+ @location = YahooWeather::Location.new root['location'].first
240
+ @units = YahooWeather::Units.new root['units'].first
241
+ @wind = YahooWeather::Wind.new root['wind'].first
242
+ @atmosphere = YahooWeather::Atmosphere.new root['atmosphere'].first
243
+
244
+ item = root['item'].first
245
+ @condition = YahooWeather::Condition.new item['condition'].first
246
+ @forecasts = []
247
+ item['forecast'].each { |forecast| @forecasts << YahooWeather::Forecast.new(forecast) }
248
+ @latitude = item['lat'].first.to_f
249
+ @longitude = item['long'].first.to_f
250
+ @page_url = item['link'].first
251
+ @title = item['title'].first
252
+ @description = item['description'].first
253
+
254
+ match_data = @@REGEXP_IMAGE.match(description)
255
+ @image_url = (match_data) ? match_data[1] : nil
256
+ end
257
+ end
258
+
259
+ # The main client object through which the Yahoo! Weather service may be accessed.
260
+ class Client
261
+ # the url with which we obtain weather information from yahoo
262
+ @@API_URL = "http://xml.weather.yahoo.com/forecastrss"
263
+
264
+ def initialize (api_url = @@API_URL)
265
+ @api_url = api_url
266
+ end
267
+
268
+ # Returns a YahooWeather::Response object detailing the current weather
269
+ # information for the specified location.
270
+ #
271
+ # +location+ can be either a US zip code or a location code. Location
272
+ # codes can be looked up at http://weather.yahoo.com, where it will appear
273
+ # in the URL that results from searching on the city or zip code. For
274
+ # instance, searching on 'Seattle, WA' results in a URL ending in
275
+ # 'USWA0395.html', so the location code for Seattle is 'USWA0395'.
276
+ #
277
+ # +units+ allows specifying whether to retrieve information in
278
+ # +Fahrenheit+ as +f+, or +Celsius+ as +c+, and defaults to +f+.
279
+ def lookup_location (location, units = 'f')
280
+ # query the service to grab the xml data
281
+ url = _request_url(location, units)
282
+ begin
283
+ response = Net::HTTP.get_response(URI.parse(url)).body.to_s
284
+ rescue
285
+ raise "failed to get weather via '#{url}': " + $!
286
+ end
287
+
288
+ # create the response object
289
+ response = XmlSimple.xml_in(response)
290
+ YahooWeather::Response.new(location, url, response)
291
+ end
292
+
293
+ private
294
+ def _request_url (location, units)
295
+ @api_url + '?p=' + URI.encode(location) + '&u=' + URI.encode(units)
296
+ end
297
+ end
298
+
299
+ private
300
+ def self._parse_time (text)
301
+ (text) ? Time.parse(text) : nil
302
+ end
303
+ end