davidjrice-hamweather 0.0.1

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