lib/barometer/query.rb in barometer-0.8.0 vs lib/barometer/query.rb in barometer-0.9.0
- old
+ new
@@ -1,172 +1,34 @@
+require_relative 'query/base'
+require_relative 'query/format'
+require_relative 'query/converter'
+require_relative 'query/service'
+
module Barometer
- #
- # 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.
- #
- class Query
+ class ConvertedQuery
+ attr_reader :q, :format, :units, :geo
- # This array defines the order to check a query for the format
- #
- FORMATS = %w(
- ShortZipcode Zipcode Postalcode WeatherID Coordinates Icao WoeID Geocode
- )
- FORMAT_MAP = {
- :short_zipcode => "ShortZipcode", :zipcode => "Zipcode",
- :postalcode => "Postalcode", :weather_id => "WeatherID",
- :coordinates => "Coordinates", :icao => "Icao",
- :woe_id => "WoeID", :geocode => "Geocode"
- }
-
- attr_writer :q
- attr_accessor :format, :country_code
- attr_accessor :geo, :timezone, :conversions
-
- def initialize(query=nil)
- return unless query
- @q = query
- self.analyze!
- @conversions = {}
+ def initialize(q, format, units=:metric, geo=nil)
+ @q = q
+ @format = format
+ @units = units
+ @geo = geo
end
- def q
- format ? Barometer::Query::Format.const_get(FORMAT_MAP[format.to_sym].to_s).convert_query(@q) : @q
+ def metric?
+ units == :metric
end
- # analyze the saved query to determine the format.
- # this delegates the detection to each formats class
- # until th right one is found
- #
- 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
+ def to_s
+ @q
end
-
- # 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
- #
- 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 we discover that the format we have is the preferred format, return it
- 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
- elsif converted_query
- 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
-
-# save the important parts of the conversion ... by saving conversion we
-# can avoid doing the same conversion multiple times
-#
-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
-
-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
- def latitude
- return nil unless self.format == Query::Format::Coordinates.format
- Query::Format::Coordinates.parse_latitude(self.q)
- end
+ module Query
+ class ConversionNotPossible < StandardError; end
+ class UnsupportedRegion < StandardError; end
- def longitude
- return nil unless self.format == Query::Format::Coordinates.format
- Query::Format::Coordinates.parse_longitude(self.q)
- end
-
+ def self.new(*args)
+ Barometer::Query::Base.new(*args)
+ end
end
end