weather-api 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ coverage
@@ -0,0 +1,5 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - rbx
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source :rubygems
2
+
3
+ # Give guard growl notifications, if on OS X
4
+ if RUBY_PLATFORM =~ /darwin/i
5
+ gem "rb-fsevent", :require => false
6
+ gem "ruby_gntp", :require => false
7
+ end
8
+
9
+ gemspec
@@ -0,0 +1,19 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+ # Capybara request specs
17
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
18
+ end
19
+
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2012 Andrew Stewart
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,42 @@
1
+ # Weather-API
2
+
3
+ A Ruby wrapper for the Yahoo! Weather XML RSS feed.
4
+
5
+ ## Installation
6
+
7
+ [sudo] gem install weather-api
8
+
9
+ ## Description
10
+
11
+ Weather-API provides an object-oriented interface to the Yahoo! Weather XML RSS feed service.
12
+
13
+ Details on the service can be found [here](http://developer.yahoo.com/weather).
14
+
15
+ ## Usage
16
+
17
+ A simple example:
18
+
19
+ require 'rubygems'
20
+ require 'weather-api'
21
+
22
+ client = Weather::API.new
23
+
24
+ # look up WOEID via http://weather.yahoo.com; enter location by city
25
+ # name or zip and WOEID is at end of resulting page url.
26
+ response = client.lookup(9830)
27
+
28
+ print <<EOT
29
+ #{response.title}
30
+ #{response.condition.temp} degrees
31
+ #{response.condition.text}
32
+ EOT
33
+
34
+ This produces:
35
+
36
+ Conditions for Ladysmith, CA at 5:00 pm PDT
37
+ 13 degrees
38
+ Cloudy
39
+
40
+ ## Copyright
41
+
42
+ Copyright (c) 2012 Andrew Stewart. See `LICENSE` file for more details.
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ task :default => :spec
5
+
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ desc 'Open an irb session preloaded with this library'
10
+ task :console do
11
+ sh 'pry -Ilib -rweather-api'
12
+ end
@@ -0,0 +1,37 @@
1
+ require 'net/http'
2
+ require 'nokogiri'
3
+
4
+ module Weather
5
+ class << self
6
+
7
+ # Alias for Weather::API.new
8
+ #
9
+ # Returns a Weather::API object
10
+ def new
11
+ Weather::API.new
12
+ end
13
+
14
+ # Delegate to Weather::API
15
+ def method_missing(method, *args, &block)
16
+ return super unless new.respond_to?(method)
17
+ new.send(method, *args, &block)
18
+ end
19
+
20
+ def respond_to?(method, include_private=false)
21
+ new.respond_to?(method, include_private) || super(method, include_private)
22
+ end
23
+ end
24
+
25
+ autoload :API, 'weather-api/api'
26
+ autoload :Astronomy, 'weather-api/astronomy'
27
+ autoload :Atmosphere, 'weather-api/atmosphere'
28
+ autoload :Condition, 'weather-api/condition'
29
+ autoload :Forecast, 'weather-api/forecast'
30
+ autoload :Image, 'weather-api/image'
31
+ autoload :Location, 'weather-api/location'
32
+ autoload :Response, 'weather-api/response'
33
+ autoload :Units, 'weather-api/units'
34
+ autoload :Utils, 'weather-api/utils'
35
+ autoload :Version, 'weather-api/version'
36
+ autoload :Wind, 'weather-api/wind'
37
+ end
@@ -0,0 +1,33 @@
1
+ module Weather
2
+ class API
3
+ # Yahoo! Weather info endpoint
4
+ ENDPOINT = "http://weather.yahooapis.com/forecastrss"
5
+
6
+ # Public: Looks up current weather information using WOEID
7
+ #
8
+ # woeid - Int - Where On Earth IDentifier -- unique ID for
9
+ # location to get weather data for. To find
10
+ # a WOEID, refer to Yahoo!'s documentation
11
+ # at http://developer.yahoo.com/weather/
12
+ #
13
+ # units - String - whether to retrieve data in Farenheit
14
+ # or Celsius. Defaults to Farenheit
15
+ #
16
+ # Returns a Weather::Response object containing forecast
17
+ def lookup(woeid, units = 'f')
18
+ url = ENDPOINT + "?w=#{CGI.escape(woeid.to_s)}&u=#{CGI.escape(units.downcase)}"
19
+
20
+ begin
21
+ response = Net::HTTP.get_response(URI.parse(url)).body.to_s
22
+ rescue => e
23
+ raise RuntimeError.new("Failed to get weather [woeid=#{woeid}, url=#{url}, e=#{e}].")
24
+ end
25
+
26
+ # parse returned XML
27
+ doc = Nokogiri::XML.parse(response)
28
+
29
+ # create response object
30
+ Weather::Response.new(woeid, url, doc)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ module Weather
2
+ class Astronomy
3
+ # a Time object containing the sunrise time for a location
4
+ attr_reader :sunrise
5
+
6
+ # a Time object containing the sunset time for a location
7
+ attr_reader :sunset
8
+
9
+ def initialize(payload)
10
+ @sunrise = Weather::Utils.parse_time payload['sunrise']
11
+ @sunset = Weather::Utils.parse_time payload['sunset']
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ module Weather
2
+ class Atmosphere
3
+ class Barometer
4
+ STEADY = 'steady'
5
+ RISING = 'rising'
6
+ FALLING = 'falling'
7
+
8
+ # list of all possible barometer constants
9
+ ALL = [STEADY, RISING, FALLING]
10
+ end
11
+
12
+ # air humidity
13
+ attr_reader :humidity
14
+
15
+ # visibility of the surroundings
16
+ attr_reader :visibility
17
+
18
+ # air pressure level
19
+ attr_reader :pressure
20
+
21
+ # barometer state, defined as one of the contants
22
+ # in Weather::Atmosphere::Barometer
23
+ attr_reader :barometer
24
+
25
+ def initialize(payload)
26
+ @humidity = payload['humidity'].to_i
27
+ @visibility = payload['visibility'].to_i
28
+ @pressure = payload['pressure'].to_f
29
+
30
+ # map barometric pressure to appropriate constant
31
+ @barometer = nil
32
+
33
+ case payload['rising'].to_i
34
+ when 0 then @barometer = Barometer::STEADY
35
+ when 1 then @barometer = Barometer::RISING
36
+ when 2 then @barometer = Barometer::FALLING
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,22 @@
1
+ module Weather
2
+ class Condition
3
+ # the weather condition code, detailed at http://developer.yahoo.com/weather
4
+ attr_reader :code
5
+
6
+ # the date and time associated with these conditions.
7
+ attr_reader :date
8
+
9
+ # the temperature of the location.
10
+ attr_reader :temp
11
+
12
+ # the brief prose text description of the weather conditions of the location.
13
+ attr_reader :text
14
+
15
+ def initialize(payload)
16
+ @code = payload['code'].to_i
17
+ @date = Weather::Utils.parse_time(payload['date'])
18
+ @temp = payload['temp'].to_i
19
+ @text = payload['text']
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ module Weather
2
+ class Forecast
3
+ # the brief name of the day associated with the forecast
4
+ attr_reader :day
5
+
6
+ # the date associated with the forecast.
7
+ attr_reader :date
8
+
9
+ # the low temperature forecasted.
10
+ attr_reader :low
11
+
12
+ # the high temperature forecasted.
13
+ attr_reader :high
14
+
15
+ # the brief prose text description of the forecasted weather conditions.
16
+ attr_reader :text
17
+
18
+ # the weather condition code, detailed at http://developer.yahoo.com/weather
19
+ attr_reader :code
20
+
21
+ def initialize(payload)
22
+ @day = payload['day']
23
+ @date = Weather::Utils.parse_time(payload['date'])
24
+ @low = payload['low'].to_i
25
+ @high = payload['high'].to_i
26
+ @text = payload['text']
27
+ @code = payload['code'].to_i
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ module Weather
2
+ class Image
3
+ # the image height in pixels
4
+ attr_reader :height
5
+
6
+ # the image width in pixels
7
+ attr_reader :width
8
+
9
+ # the full URL to the image
10
+ attr_reader :url
11
+
12
+ # the link to the Yahoo! Weather home page
13
+ attr_reader :link
14
+
15
+ # the title of the image
16
+ attr_reader :title
17
+
18
+ def initialize(payload)
19
+ @height = payload.xpath('height').first.content.to_i
20
+ @width = payload.xpath('width').first.content.to_i
21
+ @url = payload.xpath('url').first.content
22
+ @link = payload.xpath('link').first.content
23
+ @title = payload.xpath('title').first.content
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ module Weather
2
+ class Location
3
+ # the name of the city
4
+ attr_reader :city
5
+
6
+ # the name of the country
7
+ attr_reader :country
8
+
9
+ # name of the region, such as a state or province
10
+ attr_reader :region
11
+
12
+ def initialize(payload)
13
+ @city = payload['city']
14
+ @country = payload['country']
15
+ @region = payload['region']
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,85 @@
1
+ module Weather
2
+ class Response
3
+ # a Weather::Astronomy object containing sunrise and sunset
4
+ # information for the requested location
5
+ attr_reader :astronomy
6
+
7
+ # a Weather::Location object containing the geographical
8
+ # names of the requested location
9
+ attr_reader :location
10
+
11
+ # a Weather::Units object containig the units corresponding
12
+ # to the information contained in the response
13
+ attr_reader :units
14
+
15
+ # a Weather::Wind object containing the wind information
16
+ # for the requested location
17
+ attr_reader :wind
18
+
19
+ # a Weather::Atmosphere object containing the atmosphere
20
+ # information for the requested location
21
+ attr_reader :atmosphere
22
+
23
+ # a Weather::Condition object detailing the current
24
+ # conditions of the requested location
25
+ attr_reader :condition
26
+
27
+ # a collection of Weather::Forecast objects containing
28
+ # high-level forecasted weather for upcoming days
29
+ attr_reader :forecasts
30
+
31
+ # the HTML summarizing current weather conditions for
32
+ # the requested location
33
+ attr_reader :description
34
+
35
+ # a Weather::Image object containing an image icon
36
+ # representing the current weather for the requested location
37
+ attr_reader :image
38
+
39
+ # the latitude for the requested location
40
+ attr_reader :latitude
41
+
42
+ # the longitude for the requested location
43
+ attr_reader :longitude
44
+
45
+ # the location string initially requested of the service.
46
+ attr_reader :request_location
47
+
48
+ # the url with which the Yahoo! Weather service was
49
+ # accessed to build the response
50
+ attr_reader :request_url
51
+
52
+ # the title of the weather information for the requested location
53
+ attr_reader :title
54
+
55
+ def initialize(request_location, request_url, doc)
56
+ # save the request params
57
+ @request_location = request_location
58
+ @request_url = request_url
59
+
60
+ # parse the xml element to get response data
61
+ root = doc.xpath('/rss/channel').first
62
+
63
+ @astronomy = Weather::Astronomy.new(root.xpath('yweather:astronomy').first)
64
+ @location = Weather::Location.new(root.xpath('yweather:location').first)
65
+ @units = Weather::Units.new(root.xpath('yweather:units').first)
66
+ @wind = Weather::Wind.new(root.xpath('yweather:wind').first)
67
+ @atmosphere = Weather::Atmosphere.new(root.xpath('yweather:atmosphere').first)
68
+ @image = Weather::Image.new(root.xpath('image').first)
69
+
70
+ item = root.xpath('item').first
71
+ @forecasts = []
72
+
73
+ @condition = Weather::Condition.new(item.xpath('yweather:condition').first)
74
+
75
+ item.xpath('yweather:forecast').each do |forecast|
76
+ @forecasts << Weather::Forecast.new(forecast)
77
+ end
78
+
79
+ @latitude = item.xpath('geo:lat').first.content.to_f
80
+ @longitude = item.xpath('geo:long').first.content.to_f
81
+ @title = item.xpath('title').first.content
82
+ @description = item.xpath('description').first.content
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,29 @@
1
+ module Weather
2
+ class Units
3
+ FARENHEIT = 'f'
4
+ CELSIUS = 'c'
5
+
6
+ # the unit in which temperature is measured
7
+ # e.g. F for Farenheit, and C for Celsius
8
+ attr_reader :temperature
9
+
10
+ # the unit in which distance is measured
11
+ # e.g. mi for miles, and km for kilometers
12
+ attr_reader :distance
13
+
14
+ # the unit in which pressure is measured
15
+ # e.g in for inches, and cm for centimeters
16
+ attr_reader :pressure
17
+
18
+ # the unit in which speed is measured
19
+ # e.g. mph for miles per hour, and kph for kilometers per hour
20
+ attr_reader :speed
21
+
22
+ def initialize(payload)
23
+ @temperature = payload['temperature']
24
+ @distance = payload['distance']
25
+ @pressure = payload['pressure']
26
+ @speed = payload['speed']
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ require 'chronic'
2
+
3
+ module Weather
4
+ class Utils
5
+
6
+ # Attempts to convert passed text into a Time object
7
+ #
8
+ # Returns a Time object or nil
9
+ def self.parse_time(text)
10
+ begin
11
+ Time.parse(text)
12
+ rescue ArgumentError
13
+ Chronic.parse(text)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,39 @@
1
+ module Weather
2
+ class Version
3
+
4
+ # The current major version number
5
+ #
6
+ # Returns an int
7
+ def self.major
8
+ 1
9
+ end
10
+
11
+ # The current minor version number
12
+ #
13
+ # Returns an int
14
+ def self.minor
15
+ 0
16
+ end
17
+
18
+ # The current patch version number
19
+ #
20
+ # Returns an int
21
+ def self.patch
22
+ 0
23
+ end
24
+
25
+ # The current pre version number
26
+ #
27
+ # Returns an int
28
+ def self.pre
29
+ nil
30
+ end
31
+
32
+ # Bundles up the version number into a string
33
+ #
34
+ # Returns the current version number as a string
35
+ def self.to_s
36
+ [major, minor, patch, pre].compact.join('.')
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,18 @@
1
+ module Weather
2
+ class Wind
3
+ # the temperature, with wind chill factored in
4
+ attr_reader :chill
5
+
6
+ # the direction of the wind in degrees
7
+ attr_reader :direction
8
+
9
+ # the windspeed
10
+ attr_reader :speed
11
+
12
+ def initialize(payload)
13
+ @chill = payload['chill'].to_i
14
+ @direction = payload['direction'].to_i
15
+ @speed = payload['speed'].to_i
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ require 'helper'
2
+
3
+ describe Weather::API do
4
+ it 'should alias Weather to Weather::API' do
5
+ @api = Weather.new
6
+ @api.should be_a Weather::API
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ require 'helper'
2
+
3
+ describe Weather::Astronomy do
4
+ use_vcr_cassette
5
+
6
+ before do
7
+ @client = Weather::API.new
8
+ @response = @client.lookup(9848)
9
+ end
10
+
11
+ it 'should contain Time objects for sunrise and sunset' do
12
+ @response.astronomy.sunrise.should be_a Time
13
+ @response.astronomy.sunset.should be_a Time
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ require 'helper'
2
+
3
+ describe Weather::Atmosphere do
4
+ use_vcr_cassette
5
+
6
+ before do
7
+ @client = Weather::API.new
8
+ @response = @client.lookup(9848)
9
+ end
10
+
11
+ it 'should contain a string indicating barometric pressure' do
12
+ @response.atmosphere.barometer.should be_a String
13
+ end
14
+
15
+ it 'should contain integers representing humidity and visibility' do
16
+ @response.atmosphere.humidity.should be_a Integer
17
+ @response.atmosphere.visibility.should be_a Integer
18
+ end
19
+
20
+ it 'should contain a float indicating atmospheric pressure' do
21
+ @response.atmosphere.pressure.should be_a Float
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ require 'helper'
2
+
3
+ describe Weather::Condition do
4
+ use_vcr_cassette
5
+
6
+ before do
7
+ @client = Weather::API.new
8
+ @response = @client.lookup(9848)
9
+ end
10
+
11
+ it 'should contain a weather condition code, a date, a temperature, and a description' do
12
+ @response.condition.code.should be_a Integer
13
+ @response.condition.date.should be_a Time
14
+ @response.condition.temp.should be_a Integer
15
+ @response.condition.text.should be_a String
16
+ end
17
+ end
@@ -0,0 +1,32 @@
1
+ require 'helper'
2
+
3
+ describe Weather::Forecast do
4
+ use_vcr_cassette
5
+
6
+ before do
7
+ client = Weather::API.new
8
+ response = client.lookup(9848)
9
+ @forecast = response.forecasts[0]
10
+ end
11
+
12
+ it 'should have an associated date' do
13
+ @forecast.date.should be_a Time
14
+ end
15
+
16
+ it 'should contain high and low forecasts' do
17
+ @forecast.high.should be_a Integer
18
+ @forecast.low.should be_a Integer
19
+ end
20
+
21
+ it 'should contain the name of the day associated with the forecast' do
22
+ @forecast.day.should be_a String
23
+ end
24
+
25
+ it 'should have a weather condition code' do
26
+ @forecast.code.should be_a Integer
27
+ end
28
+
29
+ it 'should have a brief description of the forecasted conditions' do
30
+ @forecast.text.should be_a String
31
+ end
32
+ end
@@ -0,0 +1,21 @@
1
+ require 'helper'
2
+
3
+ describe Weather::Image do
4
+ use_vcr_cassette
5
+
6
+ before do
7
+ @client = Weather::API.new
8
+ @response = @client.lookup(9848)
9
+ end
10
+
11
+ it 'should contain integers for image height and width' do
12
+ @response.image.height.should be_a Integer
13
+ @response.image.width.should be_a Integer
14
+ end
15
+
16
+ it 'should contain strings for the image url, link, and title' do
17
+ @response.image.url.should be_a String
18
+ @response.image.link.should be_a String
19
+ @response.image.title.should be_a String
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ require 'helper'
2
+
3
+ describe Weather::Location do
4
+ use_vcr_cassette
5
+
6
+ before do
7
+ @client = Weather::API.new
8
+ end
9
+
10
+ it 'should contain city, country, and region as strings' do
11
+ response = @client.lookup(9848)
12
+
13
+ response.location.city.should be_a String
14
+ response.location.region.should be_a String
15
+ response.location.country.should be_a String
16
+ end
17
+
18
+ it 'should be able to look up Seattle, WA' do
19
+ response = @client.lookup(2490383)
20
+
21
+ response.location.city.should == 'Seattle'
22
+ response.location.region.should == 'WA'
23
+ response.location.country.should == 'United States'
24
+ end
25
+
26
+ it 'should be able to look up Victoria, BC' do
27
+ response = @client.lookup(9848)
28
+
29
+ response.location.city.should == 'Victoria'
30
+ response.location.region.should == 'BC'
31
+ response.location.country.should == 'Canada'
32
+ end
33
+
34
+ it 'should be able to look up Nice, France' do
35
+ response = @client.lookup(614274)
36
+
37
+ response.location.city.should == 'Nice'
38
+ response.location.region.should == ''
39
+ response.location.country.should == 'France'
40
+ end
41
+ end
@@ -0,0 +1,60 @@
1
+ require 'helper'
2
+
3
+ describe Weather::Response do
4
+ use_vcr_cassette
5
+
6
+ before do
7
+ @client = Weather::API.new
8
+ @response = @client.lookup(9848)
9
+ end
10
+
11
+ it 'should contain a Weather::Astronomy object' do
12
+ @response.astronomy.should be_a Weather::Astronomy
13
+ end
14
+
15
+ it 'should contain a Weather::Location object' do
16
+ @response.location.should be_a Weather::Location
17
+ end
18
+
19
+ it 'should contain a Weather::Units object' do
20
+ @response.units.should be_a Weather::Units
21
+ end
22
+
23
+ it 'should contain a Weather::Wind object' do
24
+ @response.wind.should be_a Weather::Wind
25
+ end
26
+
27
+ it 'should contain a Weather::Atmosphere object' do
28
+ @response.atmosphere.should be_a Weather::Atmosphere
29
+ end
30
+
31
+ it 'should contain a Weather::Condition object' do
32
+ @response.condition.should be_a Weather::Condition
33
+ end
34
+
35
+ it 'should contain a collection of Weather::Forecast objects' do
36
+ @response.forecasts[0].should be_a Weather::Forecast
37
+ end
38
+
39
+ it 'should contain a Weather::Image object' do
40
+ @response.image.should be_a Weather::Image
41
+ end
42
+
43
+ it 'should contain the WOEID of the request location and the requested URL' do
44
+ @response.request_location.should == 9848
45
+ @response.request_url.should == "http://weather.yahooapis.com/forecastrss?w=9848&u=f"
46
+ end
47
+
48
+ it 'should contain a HTML description summarizing weather conditions' do
49
+ @response.description.should be_a String
50
+ end
51
+
52
+ it 'should contain a String title' do
53
+ @response.title.should be_a String
54
+ end
55
+
56
+ it 'should contain latitude and longitude in floats' do
57
+ @response.latitude.should be_a Float
58
+ @response.longitude.should be_a Float
59
+ end
60
+ end
@@ -0,0 +1,36 @@
1
+ require 'helper'
2
+
3
+ describe Weather::Units do
4
+ before do
5
+ @client = Weather::API.new
6
+ end
7
+
8
+ describe 'constants' do
9
+ it 'should have constants for celsius and farenheit' do
10
+ Weather::Units::FARENHEIT.should == 'f'
11
+ Weather::Units::CELSIUS.should == 'c'
12
+ end
13
+ end
14
+
15
+ describe 'defaults' do
16
+ use_vcr_cassette
17
+
18
+ it 'should default to imperial units' do
19
+ response = @client.lookup(9848)
20
+
21
+ response.units.distance.should == 'mi'
22
+ response.units.pressure.should == 'in'
23
+ response.units.speed.should == 'mph'
24
+ response.units.temperature.should == 'F'
25
+ end
26
+
27
+ it 'should switch to metric if specified' do
28
+ response = @client.lookup(9848, 'c')
29
+
30
+ response.units.distance.should == 'km'
31
+ response.units.pressure.should == 'mb'
32
+ response.units.speed.should == 'km/h'
33
+ response.units.temperature.should == 'C'
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ require 'helper'
2
+
3
+ describe Weather::Utils do
4
+ it 'should parse text into a Time object' do
5
+ time = Weather::Utils.parse_time('2007-01-31 12:22:26')
6
+ time.should be_a Time
7
+ end
8
+
9
+ it 'should return nil if passed nothing' do
10
+ time = Weather::Utils.parse_time('')
11
+ time.should == nil
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ require "helper"
2
+
3
+ describe Weather::Version do
4
+ it "should return a string" do
5
+ string = Weather::Version.to_s
6
+ string.should be_a String
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ require 'helper'
2
+
3
+ describe Weather::Wind do
4
+ use_vcr_cassette
5
+
6
+ before do
7
+ @client = Weather::API.new
8
+ @response = @client.lookup(9848)
9
+ end
10
+
11
+ it 'should contain chill, direction, and speed as integers' do
12
+ @response.wind.chill.should be_a Integer
13
+ @response.wind.direction.should be_a Integer
14
+ @response.wind.speed.should be_a Integer
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ require "simplecov"
2
+ SimpleCov.start
3
+
4
+ require "weather-api"
5
+
6
+ require "rspec"
7
+ require "webmock/rspec"
8
+ require "vcr"
9
+
10
+ VCR.configure do |config|
11
+ config.cassette_library_dir = "spec/fixtures/cassettes"
12
+ config.hook_into :webmock
13
+ config.ignore_localhost = true
14
+ config.default_cassette_options = { record: :new_episodes }
15
+ end
16
+
17
+ RSpec.configure do |config|
18
+ config.extend VCR::RSpec::Macros
19
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/weather-api/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Andrew Stewart"]
6
+ gem.email = ["andrew@averagestudios.com"]
7
+ gem.description = %q{A wrapper for the Yahoo! Weather XML RSS feed}
8
+ gem.summary = %q{Weather-API provides an object-oriented interface to the Yahoo! Weather XML RSS feed service.}
9
+ gem.homepage = "https://github.com/stewart/weather-api"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "weather-api"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Weather::Version.to_s
17
+
18
+ gem.add_dependency "nokogiri", "~> 1.5.2"
19
+ gem.add_dependency "chronic", "~> 0.6.7"
20
+
21
+ gem.add_development_dependency "guard-rspec", "~> 0.7.0"
22
+ gem.add_development_dependency "simplecov", "~> 0.6.1"
23
+ gem.add_development_dependency "rspec", "~> 2.9.0"
24
+ gem.add_development_dependency "webmock", "~> 1.8.6"
25
+ gem.add_development_dependency "guard", "~> 1.0.1"
26
+ gem.add_development_dependency "rake", "~> 0.9.2.2"
27
+ gem.add_development_dependency "vcr", "~> 2.0.1"
28
+ end
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: weather-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andrew Stewart
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: &70196846185740 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.5.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70196846185740
25
+ - !ruby/object:Gem::Dependency
26
+ name: chronic
27
+ requirement: &70196846185220 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.6.7
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70196846185220
36
+ - !ruby/object:Gem::Dependency
37
+ name: guard-rspec
38
+ requirement: &70196846184760 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 0.7.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70196846184760
47
+ - !ruby/object:Gem::Dependency
48
+ name: simplecov
49
+ requirement: &70196846184280 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.6.1
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70196846184280
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec
60
+ requirement: &70196846183820 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 2.9.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70196846183820
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
71
+ requirement: &70196846183360 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 1.8.6
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70196846183360
80
+ - !ruby/object:Gem::Dependency
81
+ name: guard
82
+ requirement: &70196846182900 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: 1.0.1
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70196846182900
91
+ - !ruby/object:Gem::Dependency
92
+ name: rake
93
+ requirement: &70196846182440 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ~>
97
+ - !ruby/object:Gem::Version
98
+ version: 0.9.2.2
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70196846182440
102
+ - !ruby/object:Gem::Dependency
103
+ name: vcr
104
+ requirement: &70196846181900 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 2.0.1
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: *70196846181900
113
+ description: A wrapper for the Yahoo! Weather XML RSS feed
114
+ email:
115
+ - andrew@averagestudios.com
116
+ executables: []
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - .gitignore
121
+ - .travis.yml
122
+ - Gemfile
123
+ - Guardfile
124
+ - LICENSE
125
+ - README.md
126
+ - Rakefile
127
+ - lib/weather-api.rb
128
+ - lib/weather-api/api.rb
129
+ - lib/weather-api/astronomy.rb
130
+ - lib/weather-api/atmosphere.rb
131
+ - lib/weather-api/condition.rb
132
+ - lib/weather-api/forecast.rb
133
+ - lib/weather-api/image.rb
134
+ - lib/weather-api/location.rb
135
+ - lib/weather-api/response.rb
136
+ - lib/weather-api/units.rb
137
+ - lib/weather-api/utils.rb
138
+ - lib/weather-api/version.rb
139
+ - lib/weather-api/wind.rb
140
+ - spec/cases/api_spec.rb
141
+ - spec/cases/astronomy_spec.rb
142
+ - spec/cases/atmosphere_spec.rb
143
+ - spec/cases/condition_spec.rb
144
+ - spec/cases/forecast_spec.rb
145
+ - spec/cases/image_spec.rb
146
+ - spec/cases/location_spec.rb
147
+ - spec/cases/response_spec.rb
148
+ - spec/cases/units_spec.rb
149
+ - spec/cases/utils_spec.rb
150
+ - spec/cases/version_spec.rb
151
+ - spec/cases/wind_spec.rb
152
+ - spec/helper.rb
153
+ - weather-api.gemspec
154
+ homepage: https://github.com/stewart/weather-api
155
+ licenses: []
156
+ post_install_message:
157
+ rdoc_options: []
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ none: false
168
+ requirements:
169
+ - - ! '>='
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubyforge_project:
174
+ rubygems_version: 1.8.11
175
+ signing_key:
176
+ specification_version: 3
177
+ summary: Weather-API provides an object-oriented interface to the Yahoo! Weather XML
178
+ RSS feed service.
179
+ test_files:
180
+ - spec/cases/api_spec.rb
181
+ - spec/cases/astronomy_spec.rb
182
+ - spec/cases/atmosphere_spec.rb
183
+ - spec/cases/condition_spec.rb
184
+ - spec/cases/forecast_spec.rb
185
+ - spec/cases/image_spec.rb
186
+ - spec/cases/location_spec.rb
187
+ - spec/cases/response_spec.rb
188
+ - spec/cases/units_spec.rb
189
+ - spec/cases/utils_spec.rb
190
+ - spec/cases/version_spec.rb
191
+ - spec/cases/wind_spec.rb
192
+ - spec/helper.rb