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