Class: Barometer::Query

Inherits:
Object
  • Object
show all
Defined in:
lib/barometer/query.rb

Overview

This class represents a query and can answer the questions that a Barometer will need to measure the weather

Summary:

When you create a new Query, you set the query string
ie: "New York, NY" or "90210"
The class will then determine the query string format
ie: :zipcode, :postalcode, :geocode, :coordinates
Now, when a Weather API driver asks for the query, it will prefer
certain formats, and only permit certain formats.  The Query class
will attempt to either return the query string as-is if acceptable,
or it will attempt to convert it to a format that is acceptable
(most likely this conversion will use Googles geocoding service using
the Graticule gem).  Worst case scenario is that the Weather API will
not accept the query string.

Defined Under Namespace

Classes: Format

Constant Summary collapse

FORMATS =

This array defines the order to check a query for the format

%w(
  ShortZipcode Zipcode Postalcode WeatherID Coordinates Icao Geocode
)
FORMAT_MAP =
{
  :short_zipcode => "ShortZipcode", :zipcode => "Zipcode",
  :postalcode => "Postalcode", :weather_id => "WeatherID",
  :coordinates => "Coordinates", :icao => "Icao",
  :geocode => "Geocode"
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(query = nil) ⇒ Query

Returns a new instance of Query.



36
37
38
39
40
41
# File 'lib/barometer/query.rb', line 36

def initialize(query=nil)
  return unless query
  @q = query
  self.analyze!
  @conversions = {}
end

Instance Attribute Details

#conversionsObject

Returns the value of attribute conversions.



34
35
36
# File 'lib/barometer/query.rb', line 34

def conversions
  @conversions
end

#country_codeObject

Returns the value of attribute country_code.



33
34
35
# File 'lib/barometer/query.rb', line 33

def country_code
  @country_code
end

#formatObject

Returns the value of attribute format.



33
34
35
# File 'lib/barometer/query.rb', line 33

def format
  @format
end

#geoObject

Returns the value of attribute geo.



34
35
36
# File 'lib/barometer/query.rb', line 34

def geo
  @geo
end

#qObject

Returns the value of attribute q.



33
34
35
# File 'lib/barometer/query.rb', line 33

def q
  @q
end

#timezoneObject

Returns the value of attribute timezone.



34
35
36
# File 'lib/barometer/query.rb', line 34

def timezone
  @timezone
end

Instance Method Details

#analyze!Object

analyze the saved query to determine the format. this delegates the detection to each formats class until th right one is found



47
48
49
50
51
52
53
54
55
56
# File 'lib/barometer/query.rb', line 47

def analyze!
  return unless @q
  FORMATS.each do |format|
    if Query::Format.const_get(format.to_s).is?(@q)
      @format = Query::Format.const_get(format.to_s).format
      @country_code = Query::Format.const_get(format.to_s).country_code(@q)
      break
    end
  end
end

#convert!(preferred_formats = nil) ⇒ Object

take a list of acceptable (and ordered by preference) formats and convert the current query (q) into the most preferred and acceptable format. a side effect of the conversions may reveal the country_code, if so save it

Raises:

  • (ArgumentError)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/barometer/query.rb', line 62

def convert!(preferred_formats=nil)
  raise ArgumentError unless (preferred_formats && preferred_formats.size > 0)
  
  # why convert if we are already there?
  # (except in the case that the serivce excepts coordinates and we have a
  # a geocode ... the google geocode results are superior)
  #
  skip_conversion = false
  unless (@format.to_sym == Query::Format::Geocode.format) &&
         preferred_formats.include?(Query::Format::Coordinates.format)
    if preferred_formats.include?(@format.to_sym)
      skip_conversion = true
      converted_query = self.dup
    end
  end
  
  unless skip_conversion
    # go through each acceptable format and try to convert to that
    converted = false
    converted_query = Barometer::Query.new
    preferred_formats.each do |preferred_format|
      klass = FORMAT_MAP[preferred_format.to_sym]
      if preferred_format == @format
        converted = true
        converted_query = Barometer::Query.new(@q)
      end
      unless converted
        unless converted_query = get_conversion(preferred_format)
          converted_query =  Query::Format.const_get(klass.to_s).to(self)
        end  
        converted = true if converted_query
      end
      if converted
        converted_query.country_code ||= Query::Format.const_get(klass.to_s).country_code(converted_query.q)
        post_conversion(converted_query)
        break
      end
    end
  end
  
  # force geocode?, unless we already did
  #
  if Barometer.force_geocode && !@geo
    if converted_query && converted_query.geo
      @geo = converted_query.geo
    else
      puts "enhance geocode: #{converted_query.q}" if Barometer::debug?
      geo_query = Query::Format::Coordinates.to(converted_query)
      @geo = geo_query.geo if (geo_query && geo_query.geo)
      converted_query.geo = @geo.dup
    end
  end
  
  # enhance timezone?, unless we already did
  #
  if Barometer.enhance_timezone && !@timezone
    if converted_query && converted_query.timezone
      @geo = converted_query.timezone
    elsif @geo && @geo.latitude && @geo.longitude
      puts "enhance timezone: #{@geo.latitude}, #{@geo.longitude}" if Barometer::debug?
      @timezone = WebService::Timezone.fetch(@geo.latitude,@geo.longitude)
      converted_query.timezone = @timezone.dup
    end
  end
  
  converted_query
end

#get_conversion(format) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/barometer/query.rb', line 141

def get_conversion(format)
  return nil unless format && @conversions
  puts "found: #{self.format} -> #{format.to_sym} = #{self.q} -> #{@conversions[format.to_sym]}" if Barometer::debug? && @conversions.has_key?(format.to_sym)
  # re-constuct converted query
  if q = @conversions[format.to_sym]
    converted_query = self.dup
    converted_query.q = q
    converted_query.format = format
    converted_query
  else
    nil
  end
end

#post_conversion(converted_query) ⇒ Object

save the important parts of the conversion … by saving conversion we can avoid doing the same conversion multiple times



133
134
135
136
137
138
139
# File 'lib/barometer/query.rb', line 133

def post_conversion(converted_query)
  return unless (converted_query && converted_query.q && converted_query.format)
  @conversions = {} unless @conversions
  return if @conversions.has_key?(converted_query.format.to_sym)
  puts "store: #{self.format} -> #{converted_query.format.to_sym} = #{self.q} -> #{converted_query.q}" if Barometer::debug?
  @conversions[converted_query.format.to_sym] = converted_query.q
end