weather-api 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.travis.yml +5 -0
- data/Gemfile +9 -0
- data/Guardfile +19 -0
- data/LICENSE +19 -0
- data/README.md +42 -0
- data/Rakefile +12 -0
- data/lib/weather-api.rb +37 -0
- data/lib/weather-api/api.rb +33 -0
- data/lib/weather-api/astronomy.rb +14 -0
- data/lib/weather-api/atmosphere.rb +40 -0
- data/lib/weather-api/condition.rb +22 -0
- data/lib/weather-api/forecast.rb +30 -0
- data/lib/weather-api/image.rb +26 -0
- data/lib/weather-api/location.rb +18 -0
- data/lib/weather-api/response.rb +85 -0
- data/lib/weather-api/units.rb +29 -0
- data/lib/weather-api/utils.rb +17 -0
- data/lib/weather-api/version.rb +39 -0
- data/lib/weather-api/wind.rb +18 -0
- data/spec/cases/api_spec.rb +8 -0
- data/spec/cases/astronomy_spec.rb +15 -0
- data/spec/cases/atmosphere_spec.rb +23 -0
- data/spec/cases/condition_spec.rb +17 -0
- data/spec/cases/forecast_spec.rb +32 -0
- data/spec/cases/image_spec.rb +21 -0
- data/spec/cases/location_spec.rb +41 -0
- data/spec/cases/response_spec.rb +60 -0
- data/spec/cases/units_spec.rb +36 -0
- data/spec/cases/utils_spec.rb +13 -0
- data/spec/cases/version_spec.rb +8 -0
- data/spec/cases/wind_spec.rb +16 -0
- data/spec/helper.rb +19 -0
- data/weather-api.gemspec +28 -0
- metadata +192 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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.
|
data/Rakefile
ADDED
@@ -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
|
data/lib/weather-api.rb
ADDED
@@ -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,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,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
|
data/spec/helper.rb
ADDED
@@ -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
|
data/weather-api.gemspec
ADDED
@@ -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
|