Skip to content
Snippets Groups Projects
geocoder.rb 3.11 KiB
Newer Older
  • Learn to ignore specific revisions
  • require "geocoder/configuration"
    
    require "geocoder/calculations"
    
    require "geocoder/exceptions"
    
    require "geocoder/cache"
    
    require "geocoder/request"
    
    require "geocoder/models/active_record" if defined?(::ActiveRecord)
    require "geocoder/models/mongoid" if defined?(::Mongoid)
    require "geocoder/models/mongo_mapper" if defined?(::MongoMapper)
    
    module Geocoder
      extend self
    
      ##
    
    Alex Reisner's avatar
    Alex Reisner committed
      # Search for information about an address or a set of coordinates.
    
      def search(query)
        blank_query?(query) ? [] : lookup(query).search(query)
    
    Alex Reisner's avatar
    Alex Reisner committed
      # Look up the coordinates of the given street or IP address.
    
      #
      def coordinates(address)
    
        if (results = search(address)).size > 0
          results.first.coordinates
    
      # Look up the address of the given coordinates ([lat,lon])
      # or IP address (string).
    
      def address(query)
    
        if (results = search(query)).size > 0
    
          results.first.address
    
      ##
      # The working Cache object, or +nil+ if none configured.
      #
      def cache
        if @cache.nil? and store = Configuration.cache
          @cache = Cache.new(store, Configuration.cache_prefix)
        end
        @cache
      end
    
    
    Alex Reisner's avatar
    Alex Reisner committed
      ##
      # Array of valid Lookup names.
      #
      def valid_lookups
    
        street_lookups + ip_lookups
      end
    
      ##
      # All street address lookups, default first.
      #
      def street_lookups
    
    Chris Myers's avatar
    Chris Myers committed
        [:google, :google_premier, :yahoo, :bing, :geocoder_ca, :yandex, :nominatim]
    
      end
    
      ##
      # All IP address lookups, default first.
      #
      def ip_lookups
        [:freegeoip]
    
    
      private # -----------------------------------------------------------------
    
    
    Alex Reisner's avatar
    Alex Reisner committed
      # Get a Lookup object (which communicates with the remote geocoding API).
    
      # Takes a search query and returns an IP or street address Lookup
      # depending on the query contents.
    
      def lookup(query)
        if ip_address?(query)
    
          get_lookup(ip_lookups.first)
    
    Alex Reisner's avatar
    Alex Reisner committed
        else
    
          get_lookup(Configuration.lookup || street_lookups.first)
    
    Alex Reisner's avatar
    Alex Reisner committed
      ##
      # Retrieve a Lookup object from the store.
      #
    
    Alex Reisner's avatar
    Alex Reisner committed
      def get_lookup(name)
    
        @lookups = {} unless defined?(@lookups)
        @lookups[name] = spawn_lookup(name) unless @lookups.include?(name)
    
    Alex Reisner's avatar
    Alex Reisner committed
        @lookups[name]
      end
    
    
    Alex Reisner's avatar
    Alex Reisner committed
      ##
      # Spawn a Lookup of the given name.
      #
    
    Alex Reisner's avatar
    Alex Reisner committed
      def spawn_lookup(name)
        if valid_lookups.include?(name)
          name = name.to_s
          require "geocoder/lookups/#{name}"
    
          klass = name.split("_").map{ |i| i[0...1].upcase + i[1..-1] }.join
    
          valids = valid_lookups.map(&:inspect).join(", ")
    
          raise ConfigurationError, "Please specify a valid lookup for Geocoder " +
            "(#{name.inspect} is not one of: #{valids})."
    
    Alex Reisner's avatar
    Alex Reisner committed
    
      ##
      # Does the given value look like an IP address?
      #
    
    Alex Reisner's avatar
    Alex Reisner committed
      # Does not check for actual validity, just the appearance of four
    
      # dot-delimited numbers.
    
    Alex Reisner's avatar
    Alex Reisner committed
      #
    
    Alex Reisner's avatar
    Alex Reisner committed
      def ip_address?(value)
    
        !!value.to_s.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)
    
    Alex Reisner's avatar
    Alex Reisner committed
      end
    
    
      ##
      # Is the given search query blank? (ie, should we not bother searching?)
      #
      def blank_query?(value)
    
        !!value.to_s.match(/^\s*$/)
    
    # load Railtie if Rails exists
    if defined?(Rails)
      require "geocoder/railtie"
      Geocoder::Railtie.insert
    end