barometer 0.1.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.
Files changed (61) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +266 -0
  3. data/VERSION.yml +4 -0
  4. data/bin/barometer +63 -0
  5. data/lib/barometer.rb +52 -0
  6. data/lib/barometer/base.rb +52 -0
  7. data/lib/barometer/data.rb +15 -0
  8. data/lib/barometer/data/current.rb +93 -0
  9. data/lib/barometer/data/distance.rb +131 -0
  10. data/lib/barometer/data/forecast.rb +66 -0
  11. data/lib/barometer/data/geo.rb +98 -0
  12. data/lib/barometer/data/location.rb +20 -0
  13. data/lib/barometer/data/measurement.rb +161 -0
  14. data/lib/barometer/data/pressure.rb +133 -0
  15. data/lib/barometer/data/speed.rb +147 -0
  16. data/lib/barometer/data/sun.rb +35 -0
  17. data/lib/barometer/data/temperature.rb +164 -0
  18. data/lib/barometer/data/units.rb +55 -0
  19. data/lib/barometer/data/zone.rb +124 -0
  20. data/lib/barometer/extensions/graticule.rb +50 -0
  21. data/lib/barometer/extensions/httparty.rb +21 -0
  22. data/lib/barometer/query.rb +228 -0
  23. data/lib/barometer/services.rb +6 -0
  24. data/lib/barometer/services/google.rb +146 -0
  25. data/lib/barometer/services/noaa.rb +6 -0
  26. data/lib/barometer/services/service.rb +324 -0
  27. data/lib/barometer/services/weather_bug.rb +6 -0
  28. data/lib/barometer/services/weather_dot_com.rb +6 -0
  29. data/lib/barometer/services/wunderground.rb +285 -0
  30. data/lib/barometer/services/yahoo.rb +274 -0
  31. data/lib/barometer/weather.rb +187 -0
  32. data/spec/barometer_spec.rb +162 -0
  33. data/spec/data_current_spec.rb +225 -0
  34. data/spec/data_distance_spec.rb +336 -0
  35. data/spec/data_forecast_spec.rb +150 -0
  36. data/spec/data_geo_spec.rb +90 -0
  37. data/spec/data_location_spec.rb +59 -0
  38. data/spec/data_measurement_spec.rb +411 -0
  39. data/spec/data_pressure_spec.rb +336 -0
  40. data/spec/data_speed_spec.rb +374 -0
  41. data/spec/data_sun_spec.rb +76 -0
  42. data/spec/data_temperature_spec.rb +396 -0
  43. data/spec/data_zone_spec.rb +133 -0
  44. data/spec/fixtures/current_calgary_ab.xml +1 -0
  45. data/spec/fixtures/forecast_calgary_ab.xml +1 -0
  46. data/spec/fixtures/geocode_40_73.xml +1 -0
  47. data/spec/fixtures/geocode_90210.xml +1 -0
  48. data/spec/fixtures/geocode_T5B4M9.xml +1 -0
  49. data/spec/fixtures/geocode_calgary_ab.xml +1 -0
  50. data/spec/fixtures/geocode_newyork_ny.xml +1 -0
  51. data/spec/fixtures/google_calgary_ab.xml +1 -0
  52. data/spec/fixtures/yahoo_90210.xml +1 -0
  53. data/spec/query_spec.rb +469 -0
  54. data/spec/service_google_spec.rb +144 -0
  55. data/spec/service_wunderground_spec.rb +330 -0
  56. data/spec/service_yahoo_spec.rb +299 -0
  57. data/spec/services_spec.rb +1106 -0
  58. data/spec/spec_helper.rb +14 -0
  59. data/spec/units_spec.rb +101 -0
  60. data/spec/weather_spec.rb +265 -0
  61. metadata +119 -0
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ require 'rubygems'
4
+ require 'graticule'
5
+
6
+ describe "Geo" do
7
+
8
+ describe "when initialized" do
9
+
10
+ before(:each) do
11
+ @geo = Barometer::Geo.new
12
+ end
13
+
14
+ it "responds to latitude" do
15
+ @geo.latitude.should be_nil
16
+ end
17
+
18
+ it "responds to longitude" do
19
+ @geo.longitude.should be_nil
20
+ end
21
+
22
+ it "responds to country_code" do
23
+ @geo.country_code.should be_nil
24
+ end
25
+
26
+ it "responds to locality" do
27
+ @geo.locality.should be_nil
28
+ end
29
+
30
+ it "responds to region" do
31
+ @geo.region.should be_nil
32
+ end
33
+
34
+ it "responds to country" do
35
+ @geo.country.should be_nil
36
+ end
37
+
38
+ it "responds to coordinates" do
39
+ @geo.longitude = "99.99"
40
+ @geo.latitude = "88.88"
41
+ @geo.coordinates.should == [@geo.latitude, @geo.longitude].join(',')
42
+ end
43
+
44
+ it "requires Graticule::Location or Hash object" do
45
+ location = Graticule::Location.new
46
+ lambda { Barometer::Geo.new(1) }.should raise_error(ArgumentError)
47
+ Barometer::Geo.new(location)
48
+ lambda { Barometer::Geo.new(location) }.should_not raise_error(ArgumentError)
49
+ lambda { Barometer::Geo.new(Hash.new) }.should_not raise_error(ArgumentError)
50
+ end
51
+
52
+ it "returns a Barometer::Geo object" do
53
+ location = Graticule::Location.new
54
+ geo = Barometer::Geo.new(location)
55
+ geo.is_a?(Barometer::Geo).should be_true
56
+ end
57
+
58
+ end
59
+
60
+ describe "when converting" do
61
+
62
+ before(:each) do
63
+ @geo = Barometer::Geo.new
64
+ end
65
+
66
+ describe "from Graticule" do
67
+
68
+ it "requires Graticule::Location object (or nil)" do
69
+ location = Graticule::Location.new
70
+ lambda { @geo.build_from_graticule(1) }.should raise_error(ArgumentError)
71
+ lambda { @geo.build_from_graticule }.should_not raise_error(ArgumentError)
72
+ lambda { @geo.build_from_graticule(location) }.should_not raise_error(ArgumentError)
73
+ end
74
+
75
+ end
76
+
77
+ describe "from HTTParty" do
78
+
79
+ it "accepts HTTParty::Response object" do
80
+ location = Hash.new
81
+ lambda { @geo.build_from_httparty(1) }.should raise_error(ArgumentError)
82
+ lambda { @geo.build_from_httparty }.should_not raise_error(ArgumentError)
83
+ lambda { @geo.build_from_httparty(location) }.should_not raise_error(ArgumentError)
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
90
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Location" do
4
+
5
+ describe "when initialized" do
6
+
7
+ before(:each) do
8
+ @location = Barometer::Location.new
9
+ end
10
+
11
+ it "responds to id" do
12
+ @location.id.should be_nil
13
+ end
14
+
15
+ it "responds to name" do
16
+ @location.name.should be_nil
17
+ end
18
+
19
+ it "responds to city" do
20
+ @location.city.should be_nil
21
+ end
22
+
23
+ it "responds to state_name" do
24
+ @location.state_name.should be_nil
25
+ end
26
+
27
+ it "responds to state_code" do
28
+ @location.state_code.should be_nil
29
+ end
30
+
31
+ it "responds to country" do
32
+ @location.country.should be_nil
33
+ end
34
+
35
+ it "responds to country_code" do
36
+ @location.country_code.should be_nil
37
+ end
38
+
39
+ it "responds to zip_code" do
40
+ @location.zip_code.should be_nil
41
+ end
42
+
43
+ it "responds to latitude" do
44
+ @location.latitude.should be_nil
45
+ end
46
+
47
+ it "responds to longitude" do
48
+ @location.longitude.should be_nil
49
+ end
50
+
51
+ it "responds to coordinates" do
52
+ @location.longitude = "99.99"
53
+ @location.latitude = "88.88"
54
+ @location.coordinates.should == [@location.latitude, @location.longitude].join(',')
55
+ end
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,411 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Measurement" do
4
+
5
+ describe "when initialized" do
6
+
7
+ before(:each) do
8
+ @measurement = Barometer::Measurement.new
9
+ end
10
+
11
+ it "responds to source" do
12
+ @measurement.source.should be_nil
13
+ end
14
+
15
+ it "stores the source" do
16
+ source = :wunderground
17
+ measurement = Barometer::Measurement.new(source)
18
+ measurement.source.should_not be_nil
19
+ measurement.source.should == source
20
+ end
21
+
22
+ it "responds to time" do
23
+ @measurement.time.should be_nil
24
+ end
25
+
26
+ it "responds to current" do
27
+ @measurement.current.should be_nil
28
+ end
29
+
30
+ it "responds to forecast (and defaults to an empty Array)" do
31
+ @measurement.forecast.should be_nil
32
+ end
33
+
34
+ it "responds to timezone" do
35
+ @measurement.timezone.should be_nil
36
+ end
37
+
38
+ it "responds to station" do
39
+ @measurement.station.should be_nil
40
+ end
41
+
42
+ it "responds to location" do
43
+ @measurement.location.should be_nil
44
+ end
45
+
46
+ it "responds to success" do
47
+ @measurement.success.should be_false
48
+ end
49
+
50
+ it "responds to current?" do
51
+ @measurement.current?.should be_false
52
+ end
53
+
54
+ it "responds to metric" do
55
+ @measurement.metric.should be_true
56
+ end
57
+
58
+ end
59
+
60
+ describe "when writing data" do
61
+
62
+ before(:each) do
63
+ @measurement = Barometer::Measurement.new
64
+ end
65
+
66
+ it "only accepts Symbol for source" do
67
+ invalid_data = 1
68
+ invalid_data.class.should_not == Symbol
69
+ lambda { @measurement.source = invalid_data }.should raise_error(ArgumentError)
70
+
71
+ valid_data = :valid
72
+ valid_data.class.should == Symbol
73
+ lambda { @measurement.source = valid_data }.should_not raise_error(ArgumentError)
74
+ end
75
+
76
+ it "only accepts Time for time" do
77
+ invalid_data = 1
78
+ invalid_data.class.should_not == Time
79
+ lambda { @measurement.time = invalid_data }.should raise_error(ArgumentError)
80
+
81
+ valid_data = Time.now.utc
82
+ valid_data.class.should == Time
83
+ lambda { @measurement.time = valid_data }.should_not raise_error(ArgumentError)
84
+ end
85
+
86
+ it "only accepts Barometer::CurrentMeasurement for current" do
87
+ invalid_data = "invalid"
88
+ invalid_data.class.should_not == Barometer::CurrentMeasurement
89
+ lambda { @measurement.current = invalid_data }.should raise_error(ArgumentError)
90
+
91
+ valid_data = Barometer::CurrentMeasurement.new
92
+ valid_data.class.should == Barometer::CurrentMeasurement
93
+ lambda { @measurement.current = valid_data }.should_not raise_error(ArgumentError)
94
+ end
95
+
96
+ it "only accepts Array for forecast" do
97
+ invalid_data = 1
98
+ invalid_data.class.should_not == Array
99
+ lambda { @measurement.forecast = invalid_data }.should raise_error(ArgumentError)
100
+
101
+ valid_data = []
102
+ valid_data.class.should == Array
103
+ lambda { @measurement.forecast = valid_data }.should_not raise_error(ArgumentError)
104
+ end
105
+
106
+ it "only accepts Barometer::Zone for timezone" do
107
+ invalid_data = 1
108
+ invalid_data.class.should_not == Barometer::Zone
109
+ lambda { @measurement.timezone = invalid_data }.should raise_error(ArgumentError)
110
+
111
+ valid_data = Barometer::Zone.new("Europe/Paris")
112
+ valid_data.class.should == Barometer::Zone
113
+ lambda { @measurement.timezone = valid_data }.should_not raise_error(ArgumentError)
114
+ end
115
+
116
+ it "only accepts Barometer::Location for station" do
117
+ invalid_data = 1
118
+ invalid_data.class.should_not == Barometer::Location
119
+ lambda { @measurement.station = invalid_data }.should raise_error(ArgumentError)
120
+
121
+ valid_data = Barometer::Location.new
122
+ valid_data.class.should == Barometer::Location
123
+ lambda { @measurement.station = valid_data }.should_not raise_error(ArgumentError)
124
+ end
125
+
126
+ it "only accepts Barometer::Location for location" do
127
+ invalid_data = 1
128
+ invalid_data.class.should_not == Barometer::Location
129
+ lambda { @measurement.location = invalid_data }.should raise_error(ArgumentError)
130
+
131
+ valid_data = Barometer::Location.new
132
+ valid_data.class.should == Barometer::Location
133
+ lambda { @measurement.location = valid_data }.should_not raise_error(ArgumentError)
134
+ end
135
+
136
+ end
137
+
138
+ describe "and the helpers" do
139
+
140
+ before(:each) do
141
+ @measurement = Barometer::Measurement.new
142
+ end
143
+
144
+ it "changes state to successful (if successful)" do
145
+ @measurement.success.should be_false
146
+ @measurement.success!
147
+ @measurement.time.should be_nil
148
+ @measurement.current.should be_nil
149
+ @measurement.success.should be_false
150
+
151
+ @measurement.current = Barometer::CurrentMeasurement.new
152
+ @measurement.current.temperature = Barometer::Temperature.new
153
+ @measurement.current.temperature.c = 10
154
+ @measurement.time.should_not be_nil
155
+ @measurement.success!
156
+ @measurement.success.should be_true
157
+ end
158
+
159
+ it "returns successful state" do
160
+ @measurement.current = Barometer::CurrentMeasurement.new
161
+ @measurement.current.temperature = Barometer::Temperature.new
162
+ @measurement.current.temperature.c = 10
163
+ @measurement.success!
164
+ @measurement.success.should be_true
165
+ @measurement.success?.should be_true
166
+ end
167
+
168
+ it "returns non-successful state" do
169
+ @measurement.success.should be_false
170
+ @measurement.success?.should be_false
171
+ end
172
+
173
+ it "stamps the time" do
174
+ @measurement.time.should be_nil
175
+ @measurement.stamp!
176
+ @measurement.time.should_not be_nil
177
+ end
178
+
179
+ it "indicates if current" do
180
+ @measurement.time.should be_nil
181
+ @measurement.current?.should be_false
182
+ @measurement.stamp!
183
+ @measurement.time.should_not be_nil
184
+ @measurement.current?.should be_true
185
+
186
+ @measurement.time -= (60*60*3)
187
+ @measurement.current?.should be_true
188
+
189
+ @measurement.time -= (60*60*5)
190
+ @measurement.current?.should be_false
191
+ end
192
+
193
+ describe "changing units" do
194
+
195
+ before(:each) do
196
+ @measurement = Barometer::Measurement.new
197
+ end
198
+
199
+ it "indicates if metric?" do
200
+ @measurement.metric.should be_true
201
+ @measurement.metric?.should be_true
202
+ @measurement.metric = false
203
+ @measurement.metric.should be_false
204
+ @measurement.metric?.should be_false
205
+ end
206
+
207
+ it "changes to imperial" do
208
+ @measurement.metric?.should be_true
209
+ @measurement.imperial!
210
+ @measurement.metric?.should be_false
211
+ end
212
+
213
+ it "changes to metric" do
214
+ @measurement.metric = false
215
+ @measurement.metric?.should be_false
216
+ @measurement.metric!
217
+ @measurement.metric?.should be_true
218
+ end
219
+
220
+ end
221
+
222
+ end
223
+
224
+ describe "when searching forecasts using 'for'" do
225
+
226
+ before(:each) do
227
+ @measurement = Barometer::Measurement.new
228
+
229
+ # create a measurement object with a forecast array that includes
230
+ # dates for 4 consecutive days starting with tommorrow
231
+ @measurement.forecast = []
232
+ 1.upto(4) do |i|
233
+ forecast_measurement = Barometer::ForecastMeasurement.new
234
+ forecast_measurement.date = Date.parse((Time.now + (i * 60 * 60 * 24)).to_s)
235
+ @measurement.forecast << forecast_measurement
236
+ end
237
+ @measurement.forecast.size.should == 4
238
+
239
+ @tommorrow = (Time.now + (60 * 60 * 24))
240
+ end
241
+
242
+ it "returns nil when there are no forecasts" do
243
+ @measurement.forecast = []
244
+ @measurement.forecast.size.should == 0
245
+ @measurement.for.should be_nil
246
+ end
247
+
248
+ it "finds the date using a String" do
249
+ tommorrow = @tommorrow.to_s
250
+ tommorrow.class.should == String
251
+ @measurement.for(tommorrow).should == @measurement.forecast.first
252
+ end
253
+
254
+ it "finds the date using a Date" do
255
+ tommorrow = Date.parse(@tommorrow.to_s)
256
+ tommorrow.class.should == Date
257
+ @measurement.for(tommorrow).should == @measurement.forecast.first
258
+ end
259
+
260
+ it "finds the date using a DateTime" do
261
+ tommorrow = DateTime.parse(@tommorrow.to_s)
262
+ tommorrow.class.should == DateTime
263
+ @measurement.for(tommorrow).should == @measurement.forecast.first
264
+ end
265
+
266
+ it "finds the date using a Time" do
267
+ @tommorrow.class.should == Time
268
+ @measurement.for(@tommorrow).should == @measurement.forecast.first
269
+ end
270
+
271
+ it "finds nothing when there is not a match" do
272
+ yesterday = (Time.now - (60 * 60 * 24))
273
+ yesterday.class.should == Time
274
+ @measurement.for(yesterday).should be_nil
275
+ end
276
+
277
+ end
278
+
279
+ describe "when answering the simple questions," do
280
+
281
+ before(:each) do
282
+ @measurement = Barometer::Measurement.new(:wunderground)
283
+ end
284
+
285
+ describe "windy?" do
286
+
287
+ it "requires threshold as a number" do
288
+ lambda { @measurement.windy?("a") }.should raise_error(ArgumentError)
289
+ lambda { @measurement.windy?(1) }.should_not raise_error(ArgumentError)
290
+ lambda { @measurement.windy?(1.1) }.should_not raise_error(ArgumentError)
291
+ end
292
+
293
+ it "requires time as a Time object" do
294
+ lambda { @measurement.windy?(1,"a") }.should raise_error(ArgumentError)
295
+ lambda { @measurement.windy?(1,Time.now.utc) }.should_not raise_error(ArgumentError)
296
+ end
297
+
298
+ it "returns true if a source returns true" do
299
+ module Barometer; class Service
300
+ def self.windy?(a=nil,b=nil,c=nil); true; end
301
+ end; end
302
+ @measurement.windy?.should be_true
303
+ end
304
+
305
+ it "returns false if a measurement returns false" do
306
+ module Barometer; class Service
307
+ def self.windy?(a=nil,b=nil,c=nil); false; end
308
+ end; end
309
+ @measurement.windy?.should be_false
310
+ end
311
+
312
+ end
313
+
314
+ describe "wet?" do
315
+
316
+ it "requires threshold as a number" do
317
+ lambda { @measurement.wet?("a") }.should raise_error(ArgumentError)
318
+ lambda { @measurement.wet?(1) }.should_not raise_error(ArgumentError)
319
+ lambda { @measurement.wet?(1.1) }.should_not raise_error(ArgumentError)
320
+ end
321
+
322
+ it "requires time as a Time object" do
323
+ lambda { @measurement.wet?(1,"a") }.should raise_error(ArgumentError)
324
+ lambda { @measurement.wet?(1,Time.now.utc) }.should_not raise_error(ArgumentError)
325
+ end
326
+
327
+ it "returns true if a source returns true" do
328
+ module Barometer; class Service
329
+ def self.wet?(a=nil,b=nil,c=nil); true; end
330
+ end; end
331
+ @measurement.wet?.should be_true
332
+ end
333
+
334
+ it "returns false if a measurement returns false" do
335
+ module Barometer; class Service
336
+ def self.wet?(a=nil,b=nil,c=nil); false; end
337
+ end; end
338
+ @measurement.wet?.should be_false
339
+ end
340
+
341
+ end
342
+
343
+ describe "day?" do
344
+
345
+ it "requires time as a Time object" do
346
+ lambda { @measurement.day?("a") }.should raise_error(ArgumentError)
347
+ lambda { @measurement.day?(Time.now.utc) }.should_not raise_error(ArgumentError)
348
+ end
349
+
350
+ it "returns true if a source returns true" do
351
+ module Barometer; class Service
352
+ def self.day?(a=nil,b=nil); true; end
353
+ end; end
354
+ @measurement.day?.should be_true
355
+ end
356
+
357
+ it "returns false if a measurement returns false" do
358
+ module Barometer; class Service
359
+ def self.day?(a=nil,b=nil); false; end
360
+ end; end
361
+ @measurement.day?.should be_false
362
+ end
363
+
364
+ end
365
+
366
+ describe "sunny?" do
367
+
368
+ it "requires time as a Time object" do
369
+ lambda { @measurement.sunny?("a") }.should raise_error(ArgumentError)
370
+ lambda { @measurement.sunny?(Time.now.utc) }.should_not raise_error(ArgumentError)
371
+ end
372
+
373
+ it "returns true if a source returns true" do
374
+ module Barometer; class Service
375
+ def self.day?(a=nil,b=nil); true; end
376
+ end; end
377
+ module Barometer; class Service
378
+ def self.sunny?(a=nil,b=nil); true; end
379
+ end; end
380
+ @measurement.sunny?.should be_true
381
+ end
382
+
383
+ it "returns false if a measurement returns false" do
384
+ module Barometer; class Service
385
+ def self.day?(a=nil,b=nil); true; end
386
+ end; end
387
+ module Barometer; class Service
388
+ def self.sunny?(a=nil,b=nil); false; end
389
+ end; end
390
+ @measurement.sunny?.should be_false
391
+ end
392
+
393
+ it "returns false if night time" do
394
+ module Barometer; class Service
395
+ def self.day?(a=nil,b=nil); true; end
396
+ end; end
397
+ module Barometer; class Service
398
+ def self.sunny?(a=nil,b=nil); true; end
399
+ end; end
400
+ @measurement.sunny?.should be_true
401
+ module Barometer; class Service
402
+ def self.day?(a=nil,b=nil); false; end
403
+ end; end
404
+ @measurement.sunny?.should be_false
405
+ end
406
+
407
+ end
408
+
409
+ end
410
+
411
+ end