Class: Weather::Forecast::Forecast

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/weather/forecast.rb

Overview

Contains several days of weather data. The forecast object includes the Enumerable mixin, so that you can iterate over all of the days in the forecast using the standard ruby mechanisms as follows:

myforecast.each do |d|
  print d.outlook
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(weather_xmldoc) ⇒ Forecast

Instantiate a Forecast object from the specified Weather.com REXML::Document.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/weather/forecast.rb', line 29

def initialize(weather_xmldoc)
  if (not weather_xmldoc.kind_of?($USE_LIBXML ? XML::Document : REXML::Document))
    raise "The xml document given to the Forecast constructor must be a valid REXML::Document or XML::Document"
  end
  
  @xml = weather_xmldoc
  
  # add the lsup (latest update) and cached_on elements to individual days to make parsing easier later on
  # FIXME: I can't seem to add the lsup as an element (which would be the consistent way to do it)... adding it as an attribute seems to work though
  dayf = $USE_LIBXML ? @xml.root.find('dayf').first : @xml.root.elements['dayf']
  lsup = $USE_LIBXML ? dayf.find_first('//dayf/lsup') : dayf.elements['lsup'] if dayf
  
  if dayf and lsup
    latest_update = lsup.text
    
    ($USE_LIBXML ? @xml.find('//dayf/day') : REXML::XPath.match(@xml, "//dayf/day")).each do |dxml|
      dxml.add_attribute "lsup", latest_update
    end
  end
end

Instance Attribute Details

#xmlObject (readonly)

Returns the value of attribute xml.



26
27
28
# File 'lib/weather/forecast.rb', line 26

def xml
  @xml
end

Instance Method Details

#cached_onObject

The date and time when this forecast was last locally cached. This attribute will be nil when the forecast comes directly from the weather.com server or when you do not have the local cache enabled. See Weather::Service#enable_cache and also the README for instructions on how to enable local caching using memcached.



140
141
142
143
# File 'lib/weather/forecast.rb', line 140

def cached_on
  cached_on = xml.root.attributes['cached_on']
  Time.parse(cached_on) if cached_on 
end

#currentObject

The current conditions as a Conditions object.



51
52
53
# File 'lib/weather/forecast.rb', line 51

def current
  CurrentConditions.new(xml.root.elements['cc'])
end

#day(num) ⇒ Object

The conditions for the given day (0 = today, 1 = tomorrow, etc.) The maximum day number depends on the data available in the xml that was used to create this Forecast.



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/weather/forecast.rb', line 62

def day(num)
  element = xml.root.elements['dayf'].elements["day[@d='#{num.to_s}']"]
  if not element
    case num
    when 0 then daydisplay = "today"
    when 1 then daydisplay = "tomorrow"
    else daydisplay = "#{num} days from now"
    end
    raise "Sorry, there is no data available for #{daydisplay}"
  else
    Day.new(element)
  end
end

#each(&block) ⇒ Object

Iterates over all of the days in this Forecast.



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/weather/forecast.rb', line 84

def each(&block)
  first = true
  ($USE_LIBXML ? @xml.find('//dayf/day') : REXML::XPath.match(@xml, "//dayf/day")).each do |dxml|
    d = Day.new(dxml)
    
    # if it is after 3 PM, use current conditions
    if Time.now > Time.local(d.date.year, d.date.month, d.date.day, 15)
      d = current
    end
    
    yield d
    
    first = false if first
  end
end

#from_cache?Boolean

True if this forecast came from the local cache; false otherwise. See Weather::Forecast.cached_on and Weather::Service#enable_cache.

Returns:

  • (Boolean)


147
148
149
# File 'lib/weather/forecast.rb', line 147

def from_cache?
  not cached_on.nil?
end

#latest_updateObject

The date and time when the conditions were last measured/forecast. Returned as a Time object.

Note that this is a bit misleading, because the Forecast actually contains two “latest update” times – one for the current conditions and the other for the future forecast. This method will return the latest update time of the future forecast. If you want the latest update time of the current conditions, you should do:

forecast.current.latest_update


131
132
133
# File 'lib/weather/forecast.rb', line 131

def latest_update
  Time.parse(xml.root.elements['dayf'].elements['lsup'].text)
end

#location_cityObject

The name of the city that this Forecast is for.



106
107
108
# File 'lib/weather/forecast.rb', line 106

def location_city
  xml.root.elements['loc'].elements['dnam'].text.split(",").first
end

#location_codeObject

The location code of the weather station that this Forecast is for.



111
112
113
# File 'lib/weather/forecast.rb', line 111

def location_code
  xml.root.elements['loc'].attributes['id']
end

#location_nameObject

The full human-readable name of the place that this Forecast is for.



101
102
103
# File 'lib/weather/forecast.rb', line 101

def location_name
  xml.root.elements['loc'].elements['dnam'].text
end

#metric?Boolean

True if the units returned by this Forecast will be in the metric system (i.e. Celcius).

Returns:

  • (Boolean)


116
117
118
# File 'lib/weather/forecast.rb', line 116

def metric?              
  xml.root.elements['head'].elements['ut'].text == "C"
end

#night(num) ⇒ Object

The conditions for the given night (0 = tonight, 1 = tomorrow night, etc.) The maximum day number depends on the data available in the xml that was used to create this Forecast.



78
79
80
81
# File 'lib/weather/forecast.rb', line 78

def night(num)
  element = xml.root.elements['dayf'].elements["day[@d='#{num.to_s}']"]
  Night.new(element)
end

#tomorrowObject

Alias for day(1)



56
57
58
# File 'lib/weather/forecast.rb', line 56

def tomorrow
  day(1)
end