davidjrice-hamweather 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,13 @@
1
+ lib/hamweather/forecast/daily.rb
2
+ lib/hamweather/forecast/hourly.rb
3
+ lib/hamweather/forecast.rb
4
+ lib/hamweather/location.rb
5
+ lib/hamweather.rb
6
+ Rakefile
7
+ sample_data.xml
8
+ spec/daily_spec.rb
9
+ spec/forecast_spec.rb
10
+ spec/hamweather_spec.rb
11
+ spec/hourly_spec.rb
12
+ spec/spec_helper.rb
13
+ Manifest
data/README ADDED
@@ -0,0 +1,73 @@
1
+ Hamweather
2
+ ==========
3
+
4
+ This is a Ruby API to an XML webservice providing weather detail for global locations.
5
+ It can handle diverse locations by Zip Code, Canadian Post code or by any international address.
6
+
7
+ * It requires a Google Maps API key: http://code.google.com/apis/maps/signup.html
8
+ * It requires a Hamweather API key, contact Hamweather to discuss: http://www.hamweather.com/
9
+
10
+ Installation
11
+ ------------
12
+ > sudo gem install hamweather
13
+
14
+ Usage
15
+ -----
16
+ require 'rubygems'
17
+ require 'hamweather'
18
+
19
+ *** Hamweather is a singleton class, it takes the two API keys as such:
20
+ Hamweather.google_maps_api_key = " ... "
21
+ Hamweather.api_key = " ... "
22
+
23
+ @location = Hamweather.locate('Belfast') # Assuming your location is unambiguous:
24
+ @forecast = Hamweather.forecast(@location) # Forecast is returned as a Hamweather::Forecast object
25
+
26
+ What 'address' to use?
27
+ ----------------------
28
+ Zip Code, Canadian Postcode, International Address - it doesn't really matter.
29
+ This API uses the Google Maps API to geolocate any address which doesn't fit either of the former
30
+ precisely.
31
+ Which means the user could input "Lodnon" and get the right location as it's parsing is intelligent.
32
+
33
+ Using Hamweather::Location
34
+ --------------------------
35
+ If the 'address' you enter is ambiguous, the API may return a hash of Location objects which you can
36
+ use to choose. Check this by: @location.kind_of?(Hash)
37
+ Otherwise @location.zipcode @location.postcode? @location.geocode? will tell you what type of
38
+ Location you have.
39
+
40
+ Using Hamweather::Forecast
41
+ --------------------------
42
+ Assuming @location has been defined, @forecast = Hamweather.forecast(@location) will return a
43
+ Hamweather::Forecast object. A Forecast object has two available hashes: dailies{} and hourlies{}
44
+ which give all available Daily forecasts and Hourly forecasts respectively. Each Daily or Hourly
45
+ forecast is a Hash of Hamweather::Forecast::Daily or Hamweather::Forecast::Hourly objects.
46
+
47
+ The Daily object has a list of it's Hourly Forecasts available to you: 'hours'
48
+ Forecast variables available in a Daily forecast are:
49
+ :high_farenheit
50
+ :high_celsius
51
+ :low_farenheit
52
+ :low_celsius
53
+ :day
54
+ :date
55
+ :expected_weather
56
+ :detail
57
+ :probability_of_preciptiation
58
+
59
+ Forecast variables available in an Hourly forecast are:
60
+ :date
61
+ :time
62
+ :expected_weather
63
+ :temp_celsius
64
+ :temp_farenheit
65
+ :probability_of_precipitation
66
+ :precipitation_millimeters
67
+ :precipitation_inches
68
+ :dew_point_celsius
69
+ :dew_point_farenheit
70
+ :relative_humidity
71
+ :wind_speed_knots
72
+ :wind_speed_mph
73
+ :wind_direction
@@ -0,0 +1,40 @@
1
+ begin
2
+ require 'echoe'
3
+
4
+ Echoe.new('hamweather', '0.0.1') do |p|
5
+ p.rubyforge_name = 'hamweather'
6
+ p.summary = "Hamweather is a Ruby client library for interacting with http://hamweather.com weather data"
7
+ p.description = "Hamweather is a Ruby client library for interacting with http://hamweather.com weather data"
8
+ p.url = "http://github.com/davidjrice/hamweather"
9
+ p.author = ['David Rice']
10
+ p.email = "david@contrast.ie"
11
+ p.dependencies = ["json"]
12
+ end
13
+
14
+ rescue LoadError => e
15
+ puts "You are missing a dependency required for meta-operations on this gem."
16
+ puts "#{e.to_s.capitalize}."
17
+ end
18
+
19
+ # add spec tasks, if you have rspec installed
20
+ begin
21
+ require 'spec/rake/spectask'
22
+
23
+ Spec::Rake::SpecTask.new("spec") do |t|
24
+ t.spec_files = FileList['spec/**/*_spec.rb']
25
+ t.spec_opts = ['--color']
26
+ end
27
+
28
+ task :test do
29
+ Rake::Task['spec'].invoke
30
+ end
31
+
32
+ Spec::Rake::SpecTask.new("coverage") do |t|
33
+ t.spec_files = FileList['spec/**/*_spec.rb']
34
+ t.spec_opts = ['--color']
35
+ t.rcov = true
36
+ t.rcov_opts = ['--exclude', '^spec,/gems/']
37
+ end
38
+
39
+
40
+ end
@@ -0,0 +1,30 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "hamweather"
3
+ s.version = "0.0.1"
4
+ s.date = "2008-10-13"
5
+ s.summary = " Ruby Client API for Hamweather Weather Service (http://www.hamweather.com)"
6
+ s.email = "david@contrast.ie"
7
+ s.homepage = "http://github.com/davidjrice/hamweather"
8
+ s.description = "Client API for Hamweather Weather Service (http://www.hamweather.com)"
9
+ s.has_rdoc = true
10
+ s.authors = ["David Rice", "David Lowry"]
11
+ s.files = ["Manifest",
12
+ "README",
13
+ "Rakefile",
14
+ "hamweather.gemspec",
15
+ "lib/hamweather/forecast/daily.rb",
16
+ "lib/hamweather/forecast/hourly.rb",
17
+ "lib/hamweather/forecast.rb",
18
+ "lib/hamweather/location.rb",
19
+ "lib/hamweather.rb"]
20
+ s.test_files = ["spec/daily_spec.rb",
21
+ "spec/forecast_spec.rb",
22
+ "spec/hamweather_spec.rb",
23
+ "spec/hourly_spec.rb",
24
+ "spec/location_spec.rb",
25
+ "spec/spec_helper.rb"]
26
+ s.rdoc_options = ["--main", "README"]
27
+ s.extra_rdoc_files = ["Manifest", "README"]
28
+ s.add_dependency("google-geo", ["> 0.0.0"])
29
+ s.add_dependency("hpricot", ["> 0.0.0"])
30
+ end
@@ -0,0 +1,44 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'hamweather/location'
3
+ require 'hamweather/forecast'
4
+ require 'hamweather/forecast/daily'
5
+ require 'hamweather/forecast/hourly'
6
+
7
+ require 'date'
8
+ require 'hpricot'
9
+
10
+ module Hamweather
11
+
12
+ class ApiKeyException < StandardError; end
13
+ class GoogleApiKeyException < StandardError; end
14
+
15
+ class UnknownAddressError < StandardError; end
16
+
17
+ class << self
18
+
19
+ attr_accessor :api_key, :google_maps_api_key
20
+ # Hamweather.api_key = "..."
21
+ # Hamweather.google_maps_api_key = "..."
22
+ # locations = Hamweather.locate "Belfast"
23
+ # Hamweather.forecast(locations.first)
24
+
25
+ def locate(place)
26
+ check_api_key
27
+ @location = Hamweather::Location.parse(place)
28
+ end
29
+
30
+ def forecast(location)
31
+ check_api_key
32
+ Hamweather::Forecast.new(location)
33
+ end
34
+
35
+ protected
36
+
37
+ def check_api_key
38
+ raise ApiKeyException.new("you must provide a Hamweather api key.") if api_key.nil?
39
+ raise ApiKeyException.new("you must provide a Google Maps api key.") if google_maps_api_key.nil?
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,54 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+
4
+ module Hamweather
5
+ class Forecast
6
+
7
+ # @forecast.each_day
8
+ # => day_proxy_object.high_farenheit
9
+ # @forecast.each_hour
10
+ # => hour_proxy_object.high_farenheit
11
+
12
+ attr_accessor :forecast, :dailies, :hourlies
13
+
14
+ def initialize(location)
15
+ # Construct url from api key, location uri
16
+ # Request url, get xml then parse
17
+ xml_data = self.class.fetch(location.to_uri).gsub!(/\n/,'')
18
+ data = Hpricot.parse(xml_data)
19
+
20
+ @dailies = {}
21
+ @hourlies = {}
22
+
23
+ data.at(:wxforecast).children.each do |day|
24
+ #TODO make ordered hash
25
+ @dailies[day[:date].to_s] = Daily.new(day)
26
+ end
27
+
28
+ data.at(:wxshortterm).children.each do |hour|
29
+ #TODO make ordered hash
30
+ @hourlies[hour[:time]] = Hourly.new(hour)
31
+ @dailies[hour[:date]].hours[hour[:time]] = Hourly.new(hour)
32
+ end
33
+ end
34
+
35
+ # TODO stub out calls to this where possible.
36
+ # TODO / or raise an error.
37
+ def self.fetch(location_uri)
38
+ Net::HTTP.get URI.parse("http://hwlite.hamweather.net/#{Hamweather.api_key}/#{location_uri}")
39
+ end
40
+
41
+ def each_day
42
+ @dailies.each_pair do |key, value|
43
+ yield value
44
+ end
45
+ end
46
+
47
+ def each_hour
48
+ @hourlies.each_pair do |key, value|
49
+ yield value
50
+ end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,25 @@
1
+ module Hamweather
2
+ class Forecast::Daily
3
+ #daily_forecast = Hpricot.parse('<FPeriod interval="1" Day="FRI" Date="2008-11-14" Wx="Chance T-storms" Icon="tstorm.gif" HiF="66" HiC="19" LoF="56" LoC="13" Pop="60" Detail="Occasional showers with a chance of thunderstorms. Areas of fog. Some thunderstorms May be severe after midnight. Lows in the mid 50s. South winds 5 to 10 mph shifting to the southwest 10 to 15 mph after midnight. Chance of rain near 100 percent."/>').root
4
+ attr_accessor :high_farenheit, :high_celsius, :low_farenheit, :low_celsius, :day, :date, :expected_weather, :detail, :probability_of_preciptiation
5
+ attr_accessor :hours
6
+
7
+ def initialize(daily_forecast)
8
+ @hours = {}
9
+ @high_farenheit = daily_forecast[:hif].to_i
10
+ @high_celsius = daily_forecast[:hic].to_i
11
+ @low_farenheit = daily_forecast[:lof].to_i
12
+ @low_celsius = daily_forecast[:loc].to_i
13
+ @date = Date.parse(daily_forecast[:date])
14
+ @expected_weather = daily_forecast[:wx]
15
+ @detail = daily_forecast[:detail]
16
+ @probability_of_preciptiation = daily_forecast[:pop].to_i
17
+ end
18
+
19
+ def each_hour
20
+ @hours.each_pair do |key, value|
21
+ yield value
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ module Hamweather
2
+ class Forecast::Hourly
3
+ #hourly_forecast = Hpricot.parse('<STPeriod interval="1" Epoch="1228298400" Day="Wed" Date="2008-12-03" Time="10:00" Wx="Partly Cloudy" Icon="pcloudy.gif" TempC="0" TempF="32" Pop="10" QPFmm="" QPFin="" DewPointC="-5" DewPointF="23" RelativeHumidity="70" WindSpeedKnots="8" WindSpeedMPH="9" WindDirectionEng="SW" />').root
4
+ attr_accessor :date, :time, :expected_weather, :temp_celsius, :temp_farenheit, :probability_of_precipitation, :precipitation_millimeters, :precipitation_inches, :dew_point_celsius, :dew_point_farenheit, :relative_humidity, :wind_speed_knots, :wind_speed_mph, :wind_direction
5
+
6
+ # def initialize(xml_data)
7
+ # hourly_forecast = Hpricot.parse(xml_data).root
8
+
9
+ def initialize(hourly_forecast)
10
+ @date = Date.parse(hourly_forecast[:date])
11
+ @time = hourly_forecast[:time]
12
+ @expected_weather = hourly_forecast[:wx]
13
+ @temp_farenheit = hourly_forecast[:tempf].to_i
14
+ @temp_celsius = hourly_forecast[:tempc].to_i
15
+ @probability_of_precipitation = hourly_forecast[:pop].to_i
16
+ @precipitation_millimeters = hourly_forecast[:qpfmm]
17
+ @precipitation_inches = hourly_forecast[:qpfin]
18
+ @dew_point_celsius = hourly_forecast[:dewpointc].to_i
19
+ @dew_point_farenheit = hourly_forecast[:dewpointf].to_i
20
+ @relative_humidity = hourly_forecast[:relativehumidity].to_i
21
+ @wind_speed_knots = hourly_forecast[:windspeedknots].to_i
22
+ @wind_speed_mph = hourly_forecast[:windspeedmph].to_i
23
+ @wind_direction = hourly_forecast[:winddirectioneng]
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,91 @@
1
+ require 'rubygems'
2
+ require 'google/geo'
3
+
4
+ module Hamweather
5
+
6
+ class Location
7
+
8
+ attr_reader :string, :address
9
+
10
+ def lat
11
+ @address.latitude
12
+ end
13
+
14
+ def lon
15
+ @address.longitude
16
+ end
17
+
18
+ def to_uri
19
+ if zipcode? || postcode?
20
+ @uri ||= "wx/#{string}.xml"
21
+ elsif geocode?
22
+ @uri ||= "wx/nearby.xml?lat=#{lat}&lon=#{lon}"
23
+ end
24
+ end
25
+
26
+ def zipcode?
27
+ @kind == :zipcode
28
+ end
29
+
30
+ def postcode?
31
+ @kind == :postcode
32
+ end
33
+
34
+ def geocode?
35
+ @kind == :geocode
36
+ end
37
+
38
+ def self.parse(string)
39
+ if is_zipcode?(string) || is_canadian_postcode?(string)
40
+ return self.new(string)
41
+ else
42
+ geocode(string)
43
+ end
44
+ end
45
+
46
+ def initialize(object)
47
+ if self.class.is_zipcode?(object)
48
+ @string = object
49
+ @kind = :zipcode
50
+ elsif self.class.is_canadian_postcode?(object)
51
+ @string = object
52
+ @kind = :postcode
53
+ elsif object.kind_of?(Google::Geo::Address)
54
+ @address = object
55
+ @kind = :geocode
56
+ end
57
+ end
58
+
59
+ def self.geocode(string)
60
+ locations = call_geocoder(string).map { |a| self.new(a) }
61
+ return locations.first if locations.size == 1
62
+ return locations
63
+ end
64
+
65
+ def self.call_geocoder(string)
66
+ geo = Google::Geo.new Hamweather.google_maps_api_key
67
+
68
+ begin
69
+ return geo.locate(string)
70
+
71
+ rescue Google::Geo::UnknownAddressError, Google::Geo::UnknownError
72
+ raise Hamweather::UnknownAddressError
73
+ end
74
+ end
75
+
76
+ def self.is_zipcode?(string)
77
+ #Address: ZIP code (US)
78
+ zip_codes_regex = /(^[0-9]{5}$)|(^[0-9]{5}-[0-9]{4}$)/
79
+ return string =~ zip_codes_regex
80
+ end
81
+
82
+ def self.is_canadian_postcode?(string)
83
+ #Rules: no D, F, I, O, Q, or U anywhere
84
+ # Basic validation: ^[ABCEGHJ-NPRSTVXY]{1}[0-9]{1}[ABCEGHJ-NPRSTV-Z]{1}[ ]?[0-9]{1}[ABCEGHJ-NPRSTV-Z]{1}[0-9]{1}$
85
+ # Extended validation: ^(A(0[ABCEGHJ-NPR]|1[ABCEGHK-NSV-Y]|2[ABHNV]|5[A]|8[A])|B(0[CEHJ-NPRSTVW]|1[ABCEGHJ-NPRSTV-Y]|2[ABCEGHJNRSTV-Z]|3[ABEGHJ-NPRSTVZ]|4[ABCEGHNPRV]|5[A]|6[L]|9[A])|C(0[AB]|1[ABCEN])|E(1[ABCEGHJNVWX]|2[AEGHJ-NPRSV]|3[ABCELNVYZ]|4[ABCEGHJ-NPRSTV-Z]|5[ABCEGHJ-NPRSTV]|6[ABCEGHJKL]|7[ABCEGHJ-NP]|8[ABCEGJ-NPRST]|9[ABCEGH])|G(0[ACEGHJ-NPRSTV-Z]|1[ABCEGHJ-NPRSTV-Y]|2[ABCEGJ-N]|3[ABCEGHJ-NZ]|4[ARSTVWXZ]|5[ABCHJLMNRTVXYZ]|6[ABCEGHJKLPRSTVWXZ]|7[ABGHJKNPSTXYZ]|8[ABCEGHJ-NPTVWYZ]|9[ABCHNPRTX])|H(0[HM]|1[ABCEGHJ-NPRSTV-Z]|2[ABCEGHJ-NPRSTV-Z]|3[ABCEGHJ-NPRSTV-Z]|4[ABCEGHJ-NPRSTV-Z]|5[AB]|7[ABCEGHJ-NPRSTV-Y]|8[NPRSTYZ]|9[ABCEGHJKPRSWX])|J(0[ABCEGHJ-NPRSTV-Z]|1[ACEGHJ-NRSTXZ]|2[ABCEGHJ-NRSTWXY]|3[ABEGHLMNPRTVXYZ]|4[BGHJ-NPRSTV-Z]|5[ABCJ-MRTV-Z]|6[AEJKNRSTVWYXZ]|7[ABCEGHJ-NPRTV-Z]|8[ABCEGHLMNPRTVXYZ]|9[ABEHJLNTVXYZ])|K(0[ABCEGHJ-M]|1[ABCEGHJ-NPRSTV-Z]|2[ABCEGHJ-MPRSTVW]|4[ABCKMPR]|6[AHJKTV]|7[ACGHK-NPRSV]|8[ABHNPRV]|9[AHJKLV])|L(0[[ABCEGHJ-NPRS]]|1[ABCEGHJ-NPRSTV-Z]|2[AEGHJMNPRSTVW]|3[BCKMPRSTVXYZ]|4[ABCEGHJ-NPRSTV-Z]|5[ABCEGHJ-NPRSTVW]|6[ABCEGHJ-MPRSTV-Z]|7[ABCEGJ-NPRST]|8[EGHJ-NPRSTVW]|9[ABCGHK-NPRSTVWYZ])|M(1[BCEGHJ-NPRSTVWX]|2[HJ-NPR]|3[ABCHJ-N]|4[ABCEGHJ-NPRSTV-Y]|5[ABCEGHJ-NPRSTVWX]|6[ABCEGHJ-NPRS]|7[AY]|8[V-Z]|9[ABCLMNPRVW])|N(0[ABCEGHJ-NPR]|1[ACEGHKLMPRST]|2[ABCEGHJ-NPRTVZ]|3[ABCEHLPRSTVWY]|4[BGKLNSTVWXZ]|5[ACHLPRV-Z]|6[ABCEGHJ-NP]|7[AGLMSTVWX]|8[AHMNPRSTV-Y]|9[ABCEGHJKVY])|P(0[ABCEGHJ-NPRSTV-Y]|1[ABCHLP]|2[ABN]|3[ABCEGLNPY]|4[NPR]|5[AEN]|6[ABC]|7[ABCEGJKL]|8[NT]|9[AN])|R(0[ABCEGHJ-M]|1[ABN]|2[CEGHJ-NPRV-Y]|3[ABCEGHJ-NPRSTV-Y]|4[AHJKL]|5[AGH]|6[MW]|7[ABCN]|8[AN]|9[A])|S(0[ACEGHJ-NP]|2[V]|3[N]|4[AHLNPRSTV-Z]|6[HJKVWX]|7[HJ-NPRSTVW]|9[AHVX])|T(0[ABCEGHJ-MPV]|1[ABCGHJ-MPRSV-Y]|2[ABCEGHJ-NPRSTV-Z]|3[ABCEGHJ-NPRZ]|4[ABCEGHJLNPRSTVX]|5[ABCEGHJ-NPRSTV-Z]|6[ABCEGHJ-NPRSTVWX]|7[AENPSVXYZ]|8[ABCEGHLNRSVWX]|9[ACEGHJKMNSVWX])|V(0[ABCEGHJ-NPRSTVWX]|1[ABCEGHJ-NPRSTV-Z]|2[ABCEGHJ-NPRSTV-Z]|3[ABCEGHJ-NRSTV-Y]|4[ABCEGK-NPRSTVWXZ]|5[ABCEGHJ-NPRSTV-Z]|6[ABCEGHJ-NPRSTV-Z]|7[ABCEGHJ-NPRSTV-Y]|8[ABCGJ-NPRSTV-Z]|9[ABCEGHJ-NPRSTV-Z])|X(0[ABCGX]|1[A])|Y(0[AB]|1[A]))[ ]?[0-9]{1}[ABCEGHJ-NPRSTV-Z]{1}[0-9]{1}$
86
+ ca_postcode_regex = /^[A-Z]{1}[\d]{1}[A-Z]{1}[ ]?[\d]{1}[A-Z]{1}[\d]{1}$/
87
+ return string =~ ca_postcode_regex
88
+ end
89
+
90
+ end
91
+ end
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ #Hpricot.parse('<FPeriod interval="1" Day="FRI" Date="2008-11-14" Wx="Chance T-storms" Icon="tstorm.gif" HiF="66" HiC="19" LoF="56" LoC="13" Pop="60" Detail="Occasional showers with a chance of thunderstorms. Areas of fog. Some thunderstorms May be severe after midnight. Lows in the mid 50s. South winds 5 to 10 mph shifting to the southwest 10 to 15 mph after midnight. Chance of rain near 100 percent."/>').root
4
+ #=> {emptyelem <fperiod loc="13" wx="Chance T-storms" hic="19" lof="56" icon="tstorm.gif" date="2008-11-14" hif="66" pop="60" day="FRI" interval="1" detail="Occasional showers with a chance of thunderstorms. Areas of fog. Some thunderstorms May be severe after midnight. Lows in the mid 50s. South winds 5 to 10 mph shifting to the southwest 10 to 15 mph after midnight. Chance of rain near 100 percent.">}
5
+
6
+ describe Hamweather::Forecast::Daily do
7
+
8
+ def test_forecast_data
9
+ <<-XML
10
+ <FPeriod interval="1" Day="FRI" Date="2008-11-14" Wx="Chance T-storms" Icon="tstorm.gif" HiF="66" HiC="19" LoF="56" LoC="13" Pop="60" Detail="Occasional showers with a chance of thunderstorms. Areas of fog. Some thunderstorms May be severe after midnight. Lows in the mid 50s. South winds 5 to 10 mph shifting to the southwest 10 to 15 mph after midnight. Chance of rain near 100 percent."/>
11
+ XML
12
+ end
13
+
14
+ before(:each) do
15
+ @daily_forecast = Hamweather::Forecast::Daily.new(Hpricot.parse(test_forecast_data).root)
16
+ end
17
+
18
+ it "@hours should contain only hours belonging to 'today'" do
19
+ @daily_forecast.each_hour do |hour|
20
+ hour.date.should_be @daily_forecast.date
21
+ end
22
+ end
23
+
24
+ it "high_farenheit should be 66 degrees" do
25
+ @daily_forecast.high_farenheit.should == 66
26
+ end
27
+
28
+ it "high_celsius should be 19 degrees" do
29
+ @daily_forecast.high_celsius.should == 19
30
+ end
31
+
32
+ it "low_farenheit should be 56 degrees" do
33
+ @daily_forecast.low_farenheit.should == 56
34
+ end
35
+
36
+ it "low_celsius should be 13 degrees" do
37
+ @daily_forecast.low_celsius.should == 13
38
+ end
39
+
40
+ it "date should be the 14th of November 2008" do
41
+ @daily_forecast.date.should == Date.parse("2008-11-14")
42
+ end
43
+
44
+ it "expected_weather should be Chance T-storms" do
45
+ @daily_forecast.expected_weather.should == "Chance T-storms"
46
+ end
47
+
48
+ it "probability_of_preciptiation should be 60 percent" do
49
+ @daily_forecast.probability_of_preciptiation.should == 60
50
+ end
51
+
52
+ it "detail should be Occasional showers with a chance of thunderstorms. Areas of fog. Some thunderstorms May be severe after midnight. Lows in the mid 50s. South winds 5 to 10 mph shifting to the southwest 10 to 15 mph after midnight. Chance of rain near 100 percent." do
53
+ @daily_forecast.detail.should == "Occasional showers with a chance of thunderstorms. Areas of fog. Some thunderstorms May be severe after midnight. Lows in the mid 50s. South winds 5 to 10 mph shifting to the southwest 10 to 15 mph after midnight. Chance of rain near 100 percent."
54
+ end
55
+ end
56
+
@@ -0,0 +1,52 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Hamweather::Forecast::Daily do
4
+
5
+ before(:each) do
6
+ setup_hamweather_api_config
7
+ end
8
+
9
+ def test_forecast_data
10
+ <<-XML
11
+ <WeatherFeed><Location ID="12834" name="Greenwich" state="NY" country="US" tz="-5" tzname="EST" ><Astro><AstroPeriod Day="WED" Date="2008-12-03" Sunrise="7:06 AM EST" Sunset="4:19 PM EST" Moonrise="11:19 AM EST" Moonset="9:45 PM EST" MoonIllum="44%" MoonAge="6" MoonPhase="Waxing Crescent Moon" MoonIcon="6" /><AstroPeriod Day="WED" Date="2008-12-03" Sunrise="7:07 AM EST" Sunset="4:19 PM EST" Moonrise="11:41 AM EST" Moonset="10:50 PM EST" MoonIllum="50%" MoonAge="7" MoonPhase="First Quarter Moon" MoonIcon="7" /></Astro><WxOb StationID="KGFL" TempC="-4" TempF="25" ApparentC="-7" ApparentF="19" DewPointC="-5" DewPointF="23" RelativeHumidity="93" WindSpeedKnots="4" WindSpeedMPH="5" WindDirection="200" WindDirectionEng="SSW" WindGustKnots="0" WindGustMPH="0" PressureMB="1022" PressureIN="30.15" Wx="Fog/mist" Icon="fog.gif" Visibility="3SM" VisibilityKM="4.83" VisibilityMI="3" ReportEpoch="1228302540" ReportDate="2008-12-03 11:09 UTC" /><WxShortTerm ID="NYZ084"><STPeriod interval="1" Epoch="1228298400" Day="Wed" Date="2008-12-03" Time="10:00" Wx="Partly Cloudy" Icon="pcloudy.gif" TempC="0" TempF="32" Pop="10" QPFmm="" QPFin="" DewPointC="-5" DewPointF="23" RelativeHumidity="70" WindSpeedKnots="8" WindSpeedMPH="9" WindDirectionEng="SW" /></WxShortTerm><WxForecast ID="NYZ084"><FPeriod interval="1" Day="FRI" Date="2008-11-14" Wx="Chance T-storms" Icon="tstorm.gif" HiF="66" HiC="19" LoF="56" LoC="13" Pop="60" Detail="Occasional showers with a chance of thunderstorms. Areas of fog. Some thunderstorms May be severe after midnight. Lows in the mid 50s. South winds 5 to 10 mph shifting to the southwest 10 to 15 mph after midnight. Chance of rain near 100 percent."/></WxForecast></Location></WeatherFeed>
12
+ XML
13
+ end
14
+
15
+ def test_location_name
16
+ "Greenwich, NY, 12834, USA"
17
+ end
18
+
19
+ before(:each) do
20
+ #@forecast = Hamweather::Forecast.new(test_forecast_data)
21
+ @forecast = Hamweather::Forecast.new(Hamweather::Location.parse(test_location_name))
22
+ end
23
+
24
+ it "dailies{} should not be empty" do
25
+ @forecast.dailies.empty?.should be_false
26
+ end
27
+
28
+ it "each_day should yield Daily objects" do
29
+ @forecast.each_day do |day|
30
+ day.class.should == Hamweather::Forecast::Daily
31
+ end
32
+ end
33
+
34
+ it "each_hour should give back a Hash of Hourly objects" do
35
+ @forecast.each_day do |day|
36
+ day.each_hour do |hour|
37
+ hour.class.should == Hamweather::Forecast::Hourly
38
+ end
39
+ end
40
+ end
41
+
42
+ it "hourlies{} should not be empty" do
43
+ @forecast.hourlies.empty?.should be_false
44
+ end
45
+
46
+ it "each_hour should yield Hourly objects" do
47
+ @forecast.each_hour do |hour|
48
+ hour.class.should == Hamweather::Forecast::Hourly
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,37 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Hamweather do
4
+
5
+ describe "with no configuration" do
6
+
7
+ it "should raise an ApiKeyException" do
8
+ lambda { Hamweather.locate('Belfast') }.should raise_error(Hamweather::ApiKeyException)
9
+ end
10
+
11
+ it "should raise an ApiKeyException" do
12
+ lambda { Hamweather.forecast(mock(Hamweather::Location)) }.should raise_error(Hamweather::ApiKeyException)
13
+ end
14
+
15
+ end
16
+
17
+ describe "with a normal configuration" do
18
+
19
+ before(:each) do
20
+ setup_google_api_config
21
+ setup_hamweather_api_config
22
+ @location = Hamweather.locate('Belfast')
23
+ @forecast = Hamweather.forecast(@location)
24
+ end
25
+
26
+ it "should give a location" do
27
+ @location.kind_of?(Hamweather::Location).should be_true
28
+ end
29
+
30
+ it "should give a forecast" do
31
+ @forecast.kind_of?(Hamweather::Forecast).should be_true
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+
@@ -0,0 +1,73 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ #Hpricot.parse('<STPeriod interval="1" Epoch="1228298400" Day="Wed" Date="2008-12-03" Time="10:00" Wx="Partly Cloudy" Icon="pcloudy.gif" TempC="0" TempF="32" Pop="10" QPFmm="" QPFin="" DewPointC="-5" DewPointF="23" RelativeHumidity="70" WindSpeedKnots="8" WindSpeedMPH="9" WindDirectionEng="SW" />').root
4
+ #=> {emptyelem <stperiod qpfmm="" wx="Partly Cloudy" relativehumidity="70" dewpointc="-5" time="10:00" icon="pcloudy.gif" date="2008-12-03" tempc="0" qpfin="" windspeedknots="8" dewpointf="23" pop="10" day="Wed" winddirectioneng="SW" tempf="32" epoch="1228298400" interval="1" windspeedmph="9">}
5
+
6
+ describe Hamweather::Forecast::Hourly do
7
+
8
+ def test_forecast_data
9
+ <<-XML
10
+ <STPeriod interval="1" Epoch="1228298400" Day="Wed" Date="2008-12-03" Time="10:00" Wx="Partly Cloudy" Icon="pcloudy.gif" TempC="0" TempF="32" Pop="10" QPFmm="" QPFin="" DewPointC="-5" DewPointF="23" RelativeHumidity="70" WindSpeedKnots="8" WindSpeedMPH="9" WindDirectionEng="SW" />
11
+ XML
12
+ end
13
+
14
+ before(:each) do
15
+ @hourly_forecast = Hamweather::Forecast::Hourly.new(Hpricot.parse(test_forecast_data).root)
16
+ end
17
+
18
+ it "date should be 3rd December 2008" do
19
+ @hourly_forecast.date.should == Date.parse("2008-12-03")
20
+ end
21
+
22
+ it "time should be 10:00" do
23
+ @hourly_forecast.time.should == "10:00"
24
+ end
25
+
26
+ it "expected_weather should be Partly Cloudy" do
27
+ @hourly_forecast.expected_weather.should == "Partly Cloudy"
28
+ end
29
+
30
+ it "temp_farenheit should be 32" do
31
+ @hourly_forecast.temp_farenheit.should == 32
32
+ end
33
+
34
+ it "temp_celsius should be 0" do
35
+ @hourly_forecast.temp_celsius.should == 0
36
+ end
37
+
38
+ it "probability_of_precipitation should be 10" do
39
+ @hourly_forecast.probability_of_precipitation.should == 10
40
+ end
41
+
42
+ it "precipitation_millimeters should be " do
43
+ @hourly_forecast.precipitation_millimeters.should == ""
44
+ end
45
+
46
+ it "precipitation_inches should be " do
47
+ @hourly_forecast.precipitation_inches.should == ""
48
+ end
49
+
50
+ it "dew_point_celsius should be -5" do
51
+ @hourly_forecast.dew_point_celsius.should == -5
52
+ end
53
+
54
+ it "dew_point_farenheit should be 23" do
55
+ @hourly_forecast.dew_point_farenheit.should == 23
56
+ end
57
+
58
+ it "relative_humidity should be 70" do
59
+ @hourly_forecast.relative_humidity.should == 70
60
+ end
61
+
62
+ it "wind_speed_knots should be 8" do
63
+ @hourly_forecast.wind_speed_knots.should == 8
64
+ end
65
+
66
+ it "wind_speed_mph should be 9" do
67
+ @hourly_forecast.wind_speed_mph.should == 9
68
+ end
69
+
70
+ it "wind_direction should be SW" do
71
+ @hourly_forecast.wind_direction.should == "SW"
72
+ end
73
+ end
@@ -0,0 +1,77 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Hamweather::Location do
4
+
5
+ before(:each) do
6
+ setup_google_api_config
7
+ end
8
+
9
+ describe "with zipcode 12834" do
10
+
11
+ # should be a valid zipcode (Greenwich, NY, USA)
12
+
13
+ before(:each) do
14
+ @location = Hamweather::Location.parse("12834")
15
+ end
16
+
17
+ it ".to_uri should be 'wx/12834.xml'" do
18
+ @location.to_uri.should == "wx/12834.xml"
19
+ end
20
+
21
+ end
22
+
23
+ describe "with postcode H0H0H0" do
24
+
25
+ # should be a valid postcode (Santa, Lapland, CA)
26
+
27
+ before(:each) do
28
+ @location = Hamweather::Location.parse("H0H0H0")
29
+ end
30
+
31
+ it ".to_uri should be 'wx/H0H0H0.xml'" do
32
+ @location.to_uri.should == "wx/H0H0H0.xml"
33
+ end
34
+
35
+ end
36
+
37
+ describe "with an unambiguous address, '575 Burton Road, Greenwich, NY, 12834'" do
38
+ #Returns one option
39
+
40
+ before(:each) do
41
+ @location = Hamweather::Location.parse('575 Burton Road, Greenwich, NY, 12834')
42
+ end
43
+
44
+ it "should return one location object" do
45
+ #Google::Geo.should_receive(:new).with('thisapikey').and_return(mock(Google::Geo))
46
+ #so if you are using should_receive i'd put it in the actual it block of the spec
47
+ #so you should create the mock object first, set an expectation that ".locate" is called on it... then set the expectation that it's instantiated too!
48
+ @location.kind_of?(Hamweather::Location).should be_true
49
+ end
50
+
51
+ it ".to_uri should be 'wx/nearby.xml?lat=-73.504265&lon=43.0676821'" do
52
+ @location.to_uri.should == "wx/nearby.xml?lat=43.0676821&lon=-73.504265"
53
+ end
54
+ end
55
+
56
+ describe "with an ambiguous address, 'Greenwich, USA" do
57
+ #Returns circa 10 options, nb, no 'NY' or 'CT' in search string
58
+ before(:each) do
59
+ @location = Hamweather::Location.parse('Greenwich, USA')
60
+ end
61
+
62
+ it "should return an array of location objects" do
63
+ @location.kind_of?(Array).should be_true
64
+ @location.should_not be_empty
65
+ end
66
+ end
67
+
68
+ describe "with an unlocatable address" do
69
+
70
+ it "should raise a Hamweather::UnknownAddressError" do
71
+
72
+ lambda { Hamweather::Location.parse('') }.should raise_error(Hamweather::UnknownAddressError)
73
+
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require File.dirname(__FILE__) + '/../lib/hamweather'
3
+
4
+
5
+ def setup_google_api_config
6
+ Hamweather.google_maps_api_key = "ABQIAAAAuC9Wz6AZ_BvsKClq3zThQhT2yXp_ZAY8_ufC3CFXhHIE1NvwkxRAjq1Mt9DYkVx1c-jcuAsAreOT_w"
7
+ end
8
+
9
+ def setup_hamweather_api_config
10
+ Hamweather.api_key = "wxC1E2gT8AY7"
11
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: davidjrice-hamweather
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - David Rice
8
+ - David Lowry
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2008-10-13 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: google-geo
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: hpricot
27
+ version_requirement:
28
+ version_requirements: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">"
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.0
33
+ version:
34
+ description: Client API for Hamweather Weather Service (http://www.hamweather.com)
35
+ email: david@contrast.ie
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files:
41
+ - Manifest
42
+ - README
43
+ files:
44
+ - Manifest
45
+ - README
46
+ - Rakefile
47
+ - hamweather.gemspec
48
+ - lib/hamweather/forecast/daily.rb
49
+ - lib/hamweather/forecast/hourly.rb
50
+ - lib/hamweather/forecast.rb
51
+ - lib/hamweather/location.rb
52
+ - lib/hamweather.rb
53
+ has_rdoc: true
54
+ homepage: http://github.com/davidjrice/hamweather
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --main
58
+ - README
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.2.0
77
+ signing_key:
78
+ specification_version: 2
79
+ summary: Ruby Client API for Hamweather Weather Service (http://www.hamweather.com)
80
+ test_files:
81
+ - spec/daily_spec.rb
82
+ - spec/forecast_spec.rb
83
+ - spec/hamweather_spec.rb
84
+ - spec/hourly_spec.rb
85
+ - spec/location_spec.rb
86
+ - spec/spec_helper.rb