Skip to content
Snippets Groups Projects
geocoder.rb 2.08 KiB
Newer Older
require "geocoder/configuration"
require "geocoder/calculations"
require "geocoder/railtie"
require "geocoder/request"
module Geocoder
  extend self

  ##
Alex Reisner's avatar
Alex Reisner committed
  # Search for information about an address or a set of coordinates.
  #
  def search(*args)
    return [] if blank_query?(args[0])
Alex Reisner's avatar
Alex Reisner committed
    ip = (args.size == 1 and ip_address?(args.first))
    lookup(ip).search(*args)
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
    end
  end

  ##
  # Look up the address of the given coordinates.
  #
  def address(latitude, longitude)
    if (results = search(latitude, longitude)).size > 0
      results.first.address
    end
  end


  # exception classes
  class Error < StandardError; end
  class ConfigurationError < Error; end


  private # -----------------------------------------------------------------

  ##
  # Get the lookup object (which communicates with the remote geocoding API).
Alex Reisner's avatar
Alex Reisner committed
  # Returns an IP address lookup if +ip+ parameter true.
Alex Reisner's avatar
Alex Reisner committed
  def lookup(ip = false)
    if ip
      get_lookup :freegeoip
    else
      get_lookup Geocoder::Configuration.lookup || :google
Alex Reisner's avatar
Alex Reisner committed
  def get_lookup(name)
    unless defined?(@lookups)
      @lookups = {}
    end
    unless @lookups.include?(name)
      @lookups[name] = spawn_lookup(name)
    end
    @lookups[name]
  end

  def spawn_lookup(name)
    if valid_lookups.include?(name)
      name = name.to_s
      require "geocoder/lookups/#{name}"
      eval("Geocoder::Lookup::#{name[0...1].upcase + name[1..-1]}.new")
Alex Reisner's avatar
Alex Reisner committed

  def valid_lookups
    [:google, :yahoo, :freegeoip]
  end

  ##
  # 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 8-bit numbers.
  #
Alex Reisner's avatar
Alex Reisner committed
  def ip_address?(value)
    value.match /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
  end

  ##
  # Is the given search query blank? (ie, should we not bother searching?)
  #
  def blank_query?(value)
    !value.to_s.match(/[A-z0-9]/)
  end
Geocoder::Railtie.insert