barometer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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