yahoo-weather 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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