diff --git a/.gitignore b/.gitignore
index a9305609fd2a51a9899e8a2ef024a70646f496d8..c94bfb4e2fb82925be8231893229c1e294f40b68 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ pkg/*
 rdoc/*
 *.gem
 .bundle
+Gemfile.lock
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f642106070e28720590bd6fa0040ef049ebb6dfd
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,19 @@
+rvm:
+  - 1.8.7
+  - 1.9.2
+  - 1.9.3
+gemfile:
+  - Gemfile
+  - gemfiles/Gemfile.mongoid-2.4.x
+env: SSL_CERT_DIR=/etc/ssl/certs
+matrix:
+  exclude:
+    - rvm: 1.8.7
+      gemfile: Gemfile
+      env: SSL_CERT_DIR=/etc/ssl/certs
+    - rvm: 1.9.2
+      gemfile: Gemfile
+      env: SSL_CERT_DIR=/etc/ssl/certs
+    - rvm: 1.9.3
+      gemfile: gemfiles/Gemfile.mongoid-2.4.x
+      env: SSL_CERT_DIR=/etc/ssl/certs
diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc
index 80b266ed33d129406bc1a24d91396e0261b3d663..f4628e246835a91ef842a7a35ed618aab35444e2 100644
--- a/CHANGELOG.rdoc
+++ b/CHANGELOG.rdoc
@@ -2,6 +2,17 @@
 
 Per-release changes to Geocoder.
 
+== 1.1.2 (2012 May 24)
+
+* Add ability to specify default units and distance calculation method (thanks github.com/abravalheri).
+* Add new (optional) configuration syntax (thanks github.com/abravalheri).
+* Add support for cache stores that provide :get and :set methods.
+* Add support for custom HTTP request headers (thanks github.com/robotmay).
+* Add Result#cache_hit attribute (thanks github.com/s01ipsist).
+* Fix: rake geocode:all wasn't properly loading namespaced classes.
+* Fix: properly recognize IP addresses with ::ffff: prefix (thanks github.com/brian-ewell).
+* Fix: avoid exception during calculations when coordinates not known (thanks github.com/flori).
+
 == 1.1.1 (2012 Feb 16)
 
 * Add distance_from_sql class method to geocoded class (thanks github.com/dwilkie).
diff --git a/Gemfile b/Gemfile
index c80ee3697054566d1a4247d80be78ec3ddfde295..b114997e63766aaffb45ad5066df769b59516390 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,3 +1,15 @@
 source "http://rubygems.org"
 
 gemspec
+
+group :development, :test do
+  gem 'rake'
+  gem 'mongoid'
+  gem 'bson_ext', :platforms => :ruby
+
+  gem 'rails'
+
+  platforms :jruby do
+  	gem 'jruby-openssl'
+  end
+end
diff --git a/README.rdoc b/README.rdoc
index 883788e5d89a199436bd6e90be123ce9f86b1a77..2d9fcb61287c53693f00223b588e8b57950c214f 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -83,6 +83,13 @@ Be sure to read <i>Latitude/Longitude Order</i> in the <i>Notes on MongoDB</i> s
 
 MongoMapper is very similar to Mongoid, just be sure to include <tt>Geocoder::Model::MongoMapper</tt>.
 
+=== Mongo Indices
+
+By default, the methods <tt>geocoded_by</tt> and <tt>reverse_geocoded_by</tt> create a geospatial index. You can avoid index creation with the <tt>:skip_index option</tt>, for example:
+
+  include Geocoder::Model::Mongoid
+  geocoded_by :address, :skip_index => true
+
 === Bulk Geocoding
 
 If you have just added geocoding to an existing application with a lot of objects you can use this Rake task to geocode them all:
@@ -191,7 +198,21 @@ If your model has +street+, +city+, +state+, and +country+ attributes you might
 For reverse geocoding you can also specify an alternate name attribute where the address will be stored, for example:
 
   reverse_geocoded_by :latitude, :longitude, :address => :location  # ActiveRecord
-  reverse_geocoded_by :coordinates, :address => :loc     # MongoDB
+  reverse_geocoded_by :coordinates, :address => :loc                # MongoDB
+
+
+== Advanced Querying
+
+When querying for objects (if you're using ActiveRecord) you can also look within a square rather than a radius (circle) by using the <tt>within_bounding_box</tt> scope:
+
+  distance = 20
+  center_point = [40.71, 100.23]
+  box = Geocoder::Calculations.bounding_box(center_point, distance)
+  Venue.within_bounding_box(box, distance)
+
+This can also dramatically improve query performance, especially when used in conjunction with indexes on the latitude/longitude columns. Note, however, that returned results do not include +distance+ and +bearing+ attributes. If you want to improve performance AND have access to distance and bearing info, use both scopes:
+
+  Venue.near(center_point, distance).within_bounding_box(box, distance)
 
 
 == Advanced Geocoding
@@ -225,32 +246,30 @@ If you're familiar with the results returned by the geocoding service you're usi
 
 == Geocoding Services
 
-By default Geocoder uses Google's geocoding API to fetch coordinates and street addresses (FreeGeoIP is used for IP address info). However there are several other APIs supported, as well as a variety of settings. Please see the listing and comparison below for details on specific geocoding services (not all settings are supported by all services). The configuration options are:
+By default Geocoder uses Google's geocoding API to fetch coordinates and street addresses (FreeGeoIP is used for IP address info). However there are several other APIs supported, as well as a variety of settings. Please see the listing and comparison below for details on specific geocoding services (not all settings are supported by all services). Some common configuration options are:
 
   # config/initializers/geocoder.rb
+  Geocoder.configure do |config|
 
-  # geocoding service (see below for supported options):
-  Geocoder::Configuration.lookup = :yahoo
+    # geocoding service (see below for supported options):
+    config.lookup = :yahoo
 
-  # to use an API key:
-  Geocoder::Configuration.api_key = "..."
+    # to use an API key:
+    config.api_key = "..."
 
-  # geocoding service request timeout, in seconds (default 3):
-  Geocoder::Configuration.timeout = 5
+    # geocoding service request timeout, in seconds (default 3):
+    config.timeout = 5
 
-  # use HTTPS for geocoding service connections:
-  Geocoder::Configuration.use_https = true
+    # set default units to kilometers:
+    config.units = :km
 
-  # language to use (for search queries and reverse geocoding):
-  Geocoder::Configuration.language = :de
+    # caching (see below for details):
+    config.cache = Redis.new
+    config.cache_prefix = "..."
 
-  # use a proxy to access the service:
-  Geocoder::Configuration.http_proxy  = "127.4.4.1"
-  Geocoder::Configuration.https_proxy = "127.4.4.2" # only if HTTPS is needed
+  end
 
-  # caching (see below for details)
-  Geocoder::Configuration.cache = Redis.new
-  Geocoder::Configuration.cache_prefix = "..."
+Please see lib/geocoder/configuration.rb for a complete list of configuration options.
 
 
 === Listing and Comparison
@@ -259,7 +278,7 @@ The following is a comparison of the supported geocoding APIs. The "Limitations"
 
 ==== Google (<tt>:google</tt>)
 
-API key:: optional (required for Premier)
+API key:: required for Premier (do NOT use a key for the free version)
 Key signup:: http://code.google.com/apis/maps/signup.html
 Quota:: 2,500 requests/day, 100,000 with Google Maps API Premier
 Region:: world
@@ -307,9 +326,8 @@ Limitations:: Please limit request rate to 1 per second and include your contact
 
 ==== Yandex (<tt>:yandex</tt>)
 
-API key:: required
-Key signup:: http://api.yandex.ru/maps/intro/concepts/intro.xml#apikey
-Quota:: ?
+API key:: none
+Quota:: 25000 requests / day
 Region:: Russia
 SSL support:: no
 Languages:: Russian, Belarusian, and Ukrainian
@@ -331,7 +349,7 @@ Limitations:: "Under no circumstances can our data be re-distributed or re-sold
 ==== FreeGeoIP
 
 API key:: none
-Quota:: ?
+Quota:: 1000 requests per hour.  After reaching the hourly quota, all of your requests will result in HTTP 403 (Forbidden) until it clears up on the next roll over.
 Region:: world
 SSL support:: no
 Languages:: English
@@ -436,7 +454,7 @@ Mongo document classes (Mongoid and MongoMapper) have a built-in +near+ scope, b
 
 === Latitude/Longitude Order
 
-Coordinates are generally printed and spoken as latitude, then logitude ([lat,lon]). Geocoder respects this convention and always expects method arguments to be given in [lat,lon] order. However, MongoDB requires that coordinates be stored in [lon,lat] order as per the GeoJSON spec (http://geojson.org/geojson-spec.html#positions), so internally they are stored "backwards." However, this does not affect order of arguments to methods when using Mongoid or MongoMapper.
+Coordinates are generally printed and spoken as latitude, then longitude ([lat,lon]). Geocoder respects this convention and always expects method arguments to be given in [lat,lon] order. However, MongoDB requires that coordinates be stored in [lon,lat] order as per the GeoJSON spec (http://geojson.org/geojson-spec.html#positions), so internally they are stored "backwards." However, this does not affect order of arguments to methods when using Mongoid or MongoMapper.
 
 To access an object's coordinates in the conventional order, use the <tt>to_coordinates</tt> instance method provided by Geocoder. For example:
 
@@ -491,4 +509,4 @@ You cannot use the +near+ scope with another scope that provides an +includes+ o
 If anyone has a more elegant solution to this problem I am very interested in seeing it.
 
 
-Copyright (c) 2009-11 Alex Reisner, released under the MIT license
+Copyright (c) 2009-12 Alex Reisner, released under the MIT license
diff --git a/gemfiles/Gemfile.mongoid-2.4.x b/gemfiles/Gemfile.mongoid-2.4.x
new file mode 100644
index 0000000000000000000000000000000000000000..e3fe031df45723a395a423308638b979b3ccac30
--- /dev/null
+++ b/gemfiles/Gemfile.mongoid-2.4.x
@@ -0,0 +1,15 @@
+source "http://rubygems.org"
+
+gemspec :path => '..'
+
+group :development, :test do
+  gem 'rake'
+  gem 'mongoid', '2.4.11'
+  gem 'bson_ext', :platforms => :ruby
+
+  gem 'rails'
+
+  platforms :jruby do
+    gem 'jruby-openssl'
+  end
+end
diff --git a/lib/generators/geocoder/config/config_generator.rb b/lib/generators/geocoder/config/config_generator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3fe3b3c17fecaeb026c87013e0a63f24c05333a8
--- /dev/null
+++ b/lib/generators/geocoder/config/config_generator.rb
@@ -0,0 +1,14 @@
+require 'rails/generators'
+
+module Geocoder
+  class ConfigGenerator < Rails::Generators::Base
+    source_root File.expand_path("../templates", __FILE__)
+
+    desc "This generator creates an initializer file at config/initializers, " +
+         "with the default configuration options for Geocoder."
+    def add_initializer
+      template "initializer.rb", "config/initializers/geocoder.rb"
+    end
+  end
+end
+
diff --git a/lib/generators/geocoder/config/templates/initializer.rb b/lib/generators/geocoder/config/templates/initializer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..078cea8b47698710866279e9f43274b7ff4e40be
--- /dev/null
+++ b/lib/generators/geocoder/config/templates/initializer.rb
@@ -0,0 +1,25 @@
+Geocoder.configure do |config|
+  ## Configurable parameters: if you wish to change some configurable
+  ## behaviour in Geocoder, feel free to uncomment the following lines
+  ## and provide custom parameters.
+
+  # config.timeout      = 3           # geocoding service timeout (secs)
+  # config.lookup       = :google     # name of geocoding service (symbol)
+  # config.language     = :en         # ISO-639 language code
+  # config.use_https    = false       # use HTTPS for lookup requests? (if supported)
+  # config.http_proxy   = nil         # HTTP proxy server (user:pass@host:port)
+  # config.https_proxy  = nil         # HTTPS proxy server (user:pass@host:port)
+  # config.api_key      = nil         # API key for geocoding service
+  # config.cache        = nil         # cache object (must respond to #[], #[]=, and #keys)
+  # config.cache_prefix = "geocoder:" # prefix (string) to use for all cache keys
+
+  ## exceptions that should not be rescued by default
+  ## (if you want to implement custom error handling);
+  ## supports SocketError and TimeoutError
+  # config.always_raise = []
+
+  ## Calculation options
+  # config.units     = :mi        # :km for kilometers or :mi for miles
+  # config.distances = :linear    # :spherical or :linear
+end
+
diff --git a/lib/geocoder.rb b/lib/geocoder.rb
index f5b9d8afb0bba9e35bfafcf6154465cbe4354a00..be59577ad0c5d2006ee3f46c0aa24133b46f6b75 100644
--- a/lib/geocoder.rb
+++ b/lib/geocoder.rb
@@ -3,9 +3,9 @@ require "geocoder/calculations"
 require "geocoder/exceptions"
 require "geocoder/cache"
 require "geocoder/request"
-require "geocoder/models/active_record"
-require "geocoder/models/mongoid"
-require "geocoder/models/mongo_mapper"
+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
@@ -115,7 +115,7 @@ module Geocoder
   # dot-delimited numbers.
   #
   def ip_address?(value)
-    !!value.to_s.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)
+    !!value.to_s.match(/^(::ffff:)?(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)
   end
 
   ##
diff --git a/lib/geocoder/cache.rb b/lib/geocoder/cache.rb
index 2465d29f43edb82c504fce6bf202387099fb6720..d4cb1ac1c9b35d31a75fc8842b451c497b472dd3 100644
--- a/lib/geocoder/cache.rb
+++ b/lib/geocoder/cache.rb
@@ -10,14 +10,24 @@ module Geocoder
     # Read from the Cache.
     #
     def [](url)
-      interpret store[key_for(url)]
+      interpret case
+        when store.respond_to?(:[])
+          store[key_for(url)]
+        when store.respond_to?(:get)
+          store.get key_for(url)
+      end
     end
 
     ##
     # Write to the Cache.
     #
     def []=(url, value)
-      store[key_for(url)] = value
+      case
+        when store.respond_to?(:[]=)
+          store[key_for(url)] = value
+        when store.respond_to?(:set)
+          store.set key_for(url), value
+      end
     end
 
     ##
diff --git a/lib/geocoder/calculations.rb b/lib/geocoder/calculations.rb
index abc8b94740fdc7bd4a6f080ce4d4d956a14d4063..a3f1ff987c66dc5ae78bdf34eb6b940bf7edbc8d 100644
--- a/lib/geocoder/calculations.rb
+++ b/lib/geocoder/calculations.rb
@@ -21,10 +21,26 @@ module Geocoder
     #
     KM_IN_MI = 0.621371192
 
+    # Not a number constant
+    NAN = defined?(::Float::NAN) ? ::Float::NAN : 0 / 0.0
+
+    ##
+    # Returns true if all given arguments are valid latitude/longitude values.
+    #
+    def coordinates_present?(*args)
+      args.each do |a|
+        # note that Float::NAN != Float::NAN
+        # still, this could probably be improved:
+        return false if (!a.is_a?(Numeric) or a.to_s == "NaN")
+      end
+      true
+    end
+
     ##
     # Distance spanned by one degree of latitude in the given units.
     #
-    def latitude_degree_distance(units = :mi)
+    def latitude_degree_distance(units = nil)
+      units ||= Geocoder::Configuration.units
       2 * Math::PI * earth_radius(units) / 360
     end
 
@@ -32,7 +48,8 @@ module Geocoder
     # Distance spanned by one degree of longitude at the given latitude.
     # This ranges from around 69 miles at the equator to zero at the poles.
     #
-    def longitude_degree_distance(latitude, units = :mi)
+    def longitude_degree_distance(latitude, units = nil)
+      units ||= Geocoder::Configuration.units
       latitude_degree_distance(units) * Math.cos(to_radians(latitude))
     end
 
@@ -49,12 +66,13 @@ module Geocoder
     #
     # The options hash supports:
     #
-    # * <tt>:units</tt> - <tt>:mi</tt> (default) or <tt>:km</tt>
+    # * <tt>:units</tt> - <tt>:mi</tt> or <tt>:km</tt>
+    #   See Geocoder::Configuration to know how configure default units.
     #
     def distance_between(point1, point2, options = {})
 
       # set default options
-      options[:units] ||= :mi
+      options[:units] ||= Geocoder::Configuration.units
 
       # convert to coordinate arrays
       point1 = extract_coordinates(point1)
@@ -81,17 +99,18 @@ module Geocoder
     # See Geocoder::Calculations.distance_between for
     # ways of specifying the points. Also accepts an options hash:
     #
-    # * <tt>:method</tt> - <tt>:linear</tt> (default) or <tt>:spherical</tt>;
+    # * <tt>:method</tt> - <tt>:linear</tt> or <tt>:spherical</tt>;
     #   the spherical method is "correct" in that it returns the shortest path
-    #   (one along a great circle) but the linear method is the default as it
-    #   is less confusing (returns due east or west when given two points with
-    #   the same latitude)
+    #   (one along a great circle) but the linear method is less confusing
+    #   (returns due east or west when given two points with the same latitude).
+    #   See Geocoder::Configuration to know how configure default method.
     #
     # Based on: http://www.movable-type.co.uk/scripts/latlong.html
     #
     def bearing_between(point1, point2, options = {})
 
       # set default options
+      options[:method] ||= Geocoder::Configuration.distances
       options[:method] = :linear unless options[:method] == :spherical
 
       # convert to coordinate arrays
@@ -177,12 +196,13 @@ module Geocoder
     # See Geocoder::Calculations.distance_between for
     # ways of specifying the point. Also accepts an options hash:
     #
-    # * <tt>:units</tt> - <tt>:mi</tt> (default) or <tt>:km</tt>
+    # * <tt>:units</tt> - <tt>:mi</tt> or <tt>:km</tt>.
+    #   See Geocoder::Configuration to know how configure default units.
     #
     def bounding_box(point, radius, options = {})
       lat,lon = extract_coordinates(point)
       radius  = radius.to_f
-      units   = options[:units] || :mi
+      units   = options[:units] || Geocoder::Configuration.units
       [
         lat - (radius / latitude_degree_distance(units)),
         lon - (radius / longitude_degree_distance(lat, units)),
@@ -219,11 +239,13 @@ module Geocoder
       end
     end
 
-    def distance_to_radians(distance, units = :mi)
+    def distance_to_radians(distance, units = nil)
+      units ||= Geocoder::Configuration.units
       distance.to_f / earth_radius(units)
     end
 
-    def radians_to_distance(radians, units = :mi)
+    def radians_to_distance(radians, units = nil)
+      units ||= Geocoder::Configuration.units
       radians * earth_radius(units)
     end
 
@@ -242,9 +264,11 @@ module Geocoder
     end
 
     ##
-    # Radius of the Earth in the given units (:mi or :km). Default is :mi.
+    # Radius of the Earth in the given units (:mi or :km).
+    # See Geocoder::Configuration to know how configure default units.
     #
-    def earth_radius(units = :mi)
+    def earth_radius(units = nil)
+      units ||= Geocoder::Configuration.units
       units == :km ? EARTH_RADIUS : to_miles(EARTH_RADIUS)
     end
 
@@ -270,10 +294,26 @@ module Geocoder
     #
     def extract_coordinates(point)
       case point
-        when Array; point
-        when String; Geocoder.coordinates(point)
-        else point.to_coordinates
+      when Array
+        if point.size == 2
+          lat, lon = point
+          if !lat.nil? && lat.respond_to?(:to_f) and
+            !lon.nil? && lon.respond_to?(:to_f)
+          then
+            return [ lat.to_f, lon.to_f ]
+          end
+        end
+      when String
+        point = Geocoder.coordinates(point) and return point
+      else
+        if point.respond_to?(:to_coordinates)
+          if Array === array = point.to_coordinates
+            return extract_coordinates(array)
+          end
+        end
       end
+      [ NAN, NAN ]
     end
   end
 end
+
diff --git a/lib/geocoder/configuration.rb b/lib/geocoder/configuration.rb
index 44baabeebf4547d063ee0798ce643a2d1aebfa86..49c4c5449000a46f19da1f1dcf5a92b1ff5d59d1 100644
--- a/lib/geocoder/configuration.rb
+++ b/lib/geocoder/configuration.rb
@@ -1,58 +1,103 @@
-module Geocoder
-  class Configuration
-
-    def self.options_and_defaults
-      [
-        # geocoding service timeout (secs)
-        [:timeout, 3],
+require 'singleton'
 
-        # name of geocoding service (symbol)
-        [:lookup, :google],
+module Geocoder
 
-        # ISO-639 language code
-        [:language, :en],
+  ##
+  # Provides convenient access to the Configuration singleton.
+  #
+  def self.configure(&block)
+    if block_given?
+      block.call(Configuration.instance)
+    else
+      Configuration.instance
+    end
+  end
 
-        # use HTTPS for lookup requests? (if supported)
-        [:use_https, false],
+  ##
+  # This class handles geocoder Geocoder configuration
+  # (geocoding service provider, caching, units of measurement, etc).
+  # Configuration can be done in two ways:
+  #
+  # 1) Using Geocoder.configure and passing a block
+  #    (useful for configuring multiple things at once):
+  #
+  #   Geocoder.configure do |config|
+  #     config.timeout      = 5
+  #     config.lookup       = :yahoo
+  #     config.api_key      = "2a9fsa983jaslfj982fjasd"
+  #     config.units        = :km
+  #   end
+  #
+  # 2) Using the Geocoder::Configuration singleton directly:
+  #
+  #   Geocoder::Configuration.language = 'pt-BR'
+  #
+  # Default values are defined in Configuration#set_defaults.
+  #
+  class Configuration
+    include Singleton
 
-        # HTTP proxy server (user:pass@host:port)
-        [:http_proxy, nil],
+    OPTIONS = [
+      :timeout,
+      :lookup,
+      :language,
+      :http_headers,
+      :use_https,
+      :http_proxy,
+      :https_proxy,
+      :api_key,
+      :cache,
+      :cache_prefix,
+      :always_raise,
+      :units,
+      :distances
+    ]
 
-        # HTTPS proxy server (user:pass@host:port)
-        [:https_proxy, nil],
+    attr_accessor *OPTIONS
 
-        # API key for geocoding service
-        # for Google Premier use a 3-element array: [key, client, channel]
-        [:api_key, nil],
+    def initialize # :nodoc
+      set_defaults
+    end
 
-        # cache object (must respond to #[], #[]=, and #keys)
-        [:cache, nil],
+    def set_defaults
+      @timeout      = 3           # geocoding service timeout (secs)
+      @lookup       = :google     # name of geocoding service (symbol)
+      @language     = :en         # ISO-639 language code
+      @http_headers = {}          # HTTP headers for lookup
+      @use_https    = false       # use HTTPS for lookup requests? (if supported)
+      @http_proxy   = nil         # HTTP proxy server (user:pass@host:port)
+      @https_proxy  = nil         # HTTPS proxy server (user:pass@host:port)
+      @api_key      = nil         # API key for geocoding service
+      @cache        = nil         # cache object (must respond to #[], #[]=, and #keys)
+      @cache_prefix = "geocoder:" # prefix (string) to use for all cache keys
 
-        # prefix (string) to use for all cache keys
-        [:cache_prefix, "geocoder:"],
+      # exceptions that should not be rescued by default
+      # (if you want to implement custom error handling);
+      # supports SocketError and TimeoutError
+      @always_raise = []
 
-        # exceptions that should not be rescued by default
-        # (if you want to implement custom error handling);
-        # supports SocketError and TimeoutError
-        [:always_raise, []]
-      ]
+      # calculation options
+      @units     = :mi     # :mi or :km
+      @distances = :linear # :linear or :spherical
     end
 
-    # define getters and setters for all configuration settings
-    self.options_and_defaults.each do |option, default|
-      class_eval(<<-END, __FILE__, __LINE__ + 1)
-
-        @@#{option} = default unless defined? @@#{option}
-
-        def self.#{option}
-          @@#{option}
-        end
+    instance_eval(OPTIONS.map do |option|
+      o = option.to_s
+      <<-EOS
+      def #{o}
+        instance.#{o}
+      end
 
-        def self.#{option}=(obj)
-          @@#{option} = obj
-        end
+      def #{o}=(value)
+        instance.#{o} = value
+      end
+      EOS
+    end.join("\n\n"))
 
-      END
+    class << self
+      def set_defaults
+        instance.set_defaults
+      end
     end
   end
 end
diff --git a/lib/geocoder/lookups/base.rb b/lib/geocoder/lookups/base.rb
index 838f633c527d76ebac3c9674785752167ec74a9b..fddf8a0d4f3dcbe5fe64c2ae530e164c18c3337c 100644
--- a/lib/geocoder/lookups/base.rb
+++ b/lib/geocoder/lookups/base.rb
@@ -1,4 +1,5 @@
 require 'net/http'
+require 'net/https'
 require 'uri'
 
 unless defined?(ActiveSupport::JSON)
@@ -33,7 +34,11 @@ module Geocoder
         else
           reverse = false
         end
-        results(query, reverse).map{ |r| result_class.new(r) }
+        results(query, reverse).map{ |r| 
+          result = result_class.new(r)
+          result.cache_hit = @cache_hit if cache
+          result
+        }
       end
 
       ##
@@ -95,7 +100,7 @@ module Geocoder
       # Return false if exception not raised.
       #
       def raise_error(error, message = nil)
-        if Geocoder::Configuration.always_raise.include?(error.class)
+        if Geocoder::Configuration.always_raise.include?( error.is_a?(Class) ? error : error.class )
           raise error, message
         else
           false
@@ -106,29 +111,25 @@ module Geocoder
       # Returns a parsed search result (Ruby hash).
       #
       def fetch_data(query, reverse = false)
-        begin
-          parse_raw_data fetch_raw_data(query, reverse)
-        rescue SocketError => err
-          raise_error(err) or warn "Geocoding API connection cannot be established."
-        rescue TimeoutError => err
-          raise_error(err) or warn "Geocoding API not responding fast enough " +
-            "(see Geocoder::Configuration.timeout to set limit)."
-        end
+        parse_raw_data fetch_raw_data(query, reverse)
+      rescue SocketError => err
+        raise_error(err) or warn "Geocoding API connection cannot be established."
+      rescue TimeoutError => err
+        raise_error(err) or warn "Geocoding API not responding fast enough " +
+          "(see Geocoder::Configuration.timeout to set limit)."
       end
 
       ##
       # Parses a raw search result (returns hash or array).
       #
       def parse_raw_data(raw_data)
-        begin
-          if defined?(ActiveSupport::JSON)
-            ActiveSupport::JSON.decode(raw_data)
-          else
-            JSON.parse(raw_data)
-          end
-        rescue
-          warn "Geocoding API's response was not valid JSON."
+        if defined?(ActiveSupport::JSON)
+          ActiveSupport::JSON.decode(raw_data)
+        else
+          JSON.parse(raw_data)
         end
+      rescue
+        warn "Geocoding API's response was not valid JSON."
       end
 
       ##
@@ -146,14 +147,17 @@ module Geocoder
         timeout(Geocoder::Configuration.timeout) do
           url = query_url(query, reverse)
           uri = URI.parse(url)
-          unless cache and body = cache[url]
+          if cache and body = cache[url]
+            @cache_hit = true
+          else
             client = http_client.new(uri.host, uri.port)
             client.use_ssl = true if Geocoder::Configuration.use_https
-            response = client.get(uri.request_uri)
+            response = client.get(uri.request_uri, Geocoder::Configuration.http_headers)
             body = response.body
             if cache and (200..399).include?(response.code.to_i)
               cache[url] = body
             end
+            @cache_hit = false
           end
           body
         end
diff --git a/lib/geocoder/lookups/freegeoip.rb b/lib/geocoder/lookups/freegeoip.rb
index 63599a487cf768bf7d56033dcd108da17752793f..a5526667cd343808446934a627d3d8f6c0dee102 100644
--- a/lib/geocoder/lookups/freegeoip.rb
+++ b/lib/geocoder/lookups/freegeoip.rb
@@ -6,6 +6,10 @@ module Geocoder::Lookup
 
     private # ---------------------------------------------------------------
 
+    def parse_raw_data(raw_data)
+      raw_data.match(/^<html><title>404/) ? nil : super(raw_data)
+    end
+
     def results(query, reverse = false)
       # don't look up a loopback address, just return the stored result
       return [reserved_result(query)] if loopback_address?(query)
diff --git a/lib/geocoder/lookups/geocoder_ca.rb b/lib/geocoder/lookups/geocoder_ca.rb
index afaf147caad696e9501e2c80ca5d7a4a69820253..32ea293ab6af7388b0484fd1676ee3af9f57f6ab 100644
--- a/lib/geocoder/lookups/geocoder_ca.rb
+++ b/lib/geocoder/lookups/geocoder_ca.rb
@@ -33,6 +33,7 @@ module Geocoder::Lookup
         params[:reverse] = 1
       else
         params[:locate] = query
+        params[:showpostal] = 1
       end
       "http://geocoder.ca/?" + hash_to_query(params)
     end
diff --git a/lib/geocoder/models/active_record.rb b/lib/geocoder/models/active_record.rb
index 67a17106accb7e66632091aac450bed5ceb2f699..29bbe5f406d5534ffc674599c28d4c86340f10ce 100644
--- a/lib/geocoder/models/active_record.rb
+++ b/lib/geocoder/models/active_record.rb
@@ -14,7 +14,9 @@ module Geocoder
           :user_address  => address_attr,
           :latitude      => options[:latitude]  || :latitude,
           :longitude     => options[:longitude] || :longitude,
-          :geocode_block => block
+          :geocode_block => block,
+          :units         => options[:units],
+          :method        => options[:method]
         )
       end
 
@@ -27,7 +29,9 @@ module Geocoder
           :fetched_address => options[:address] || :address,
           :latitude        => latitude_attr,
           :longitude       => longitude_attr,
-          :reverse_block   => block
+          :reverse_block   => block,
+          :units         => options[:units],
+          :method        => options[:method]
         )
       end
 
@@ -39,3 +43,4 @@ module Geocoder
     end
   end
 end
+
diff --git a/lib/geocoder/models/base.rb b/lib/geocoder/models/base.rb
index 836233162770542dc063784b4d448c8324792708..34853a5b7af77a6bb1b692d2d053858b7e7784d1 100644
--- a/lib/geocoder/models/base.rb
+++ b/lib/geocoder/models/base.rb
@@ -12,7 +12,9 @@ module Geocoder
         if defined?(@geocoder_options)
           @geocoder_options
         elsif superclass.respond_to?(:geocoder_options)
-          superclass.geocoder_options
+          superclass.geocoder_options || { }
+        else
+          { }
         end
       end
 
@@ -24,7 +26,6 @@ module Geocoder
         fail
       end
 
-
       private # ----------------------------------------------------------------
 
       def geocoder_init(options)
@@ -38,3 +39,4 @@ module Geocoder
     end
   end
 end
+
diff --git a/lib/geocoder/models/mongo_base.rb b/lib/geocoder/models/mongo_base.rb
index 15bbbabe848b51c99247c2339dae34b764f45b1a..fe7a0e1f5fe968b1178aaed8b655b2087816cc42 100644
--- a/lib/geocoder/models/mongo_base.rb
+++ b/lib/geocoder/models/mongo_base.rb
@@ -16,7 +16,10 @@ module Geocoder
           :geocode       => true,
           :user_address  => address_attr,
           :coordinates   => options[:coordinates] || :coordinates,
-          :geocode_block => block
+          :geocode_block => block,
+          :units         => options[:units],
+          :method        => options[:method],
+          :skip_index    => options[:skip_index] || false
         )
       end
 
@@ -28,7 +31,10 @@ module Geocoder
           :reverse_geocode => true,
           :fetched_address => options[:address] || :address,
           :coordinates     => coordinates_attr,
-          :reverse_block   => block
+          :reverse_block   => block,
+          :units           => options[:units],
+          :method          => options[:method],
+          :skip_index      => options[:skip_index] || false
         )
       end
 
@@ -36,7 +42,7 @@ module Geocoder
 
       def geocoder_init(options)
         unless geocoder_initialized?
-          @geocoder_options = {}
+          @geocoder_options = { }
           require "geocoder/stores/#{geocoder_file_name}"
           include Geocoder::Store.const_get(geocoder_module_name)
         end
@@ -44,12 +50,11 @@ module Geocoder
       end
 
       def geocoder_initialized?
-        begin
-          included_modules.include? Geocoder::Store.const_get(geocoder_module_name)
-        rescue NameError
-          false
-        end
+        included_modules.include? Geocoder::Store.const_get(geocoder_module_name)
+      rescue NameError
+        false
       end
     end
   end
 end
+
diff --git a/lib/geocoder/models/mongo_mapper.rb b/lib/geocoder/models/mongo_mapper.rb
index a093f6bf056a1418ce422c38d7c80994ae3a1011..17d83402e71e78fe65a4e97386d0582e163509fb 100644
--- a/lib/geocoder/models/mongo_mapper.rb
+++ b/lib/geocoder/models/mongo_mapper.rb
@@ -16,8 +16,10 @@ module Geocoder
 
       def geocoder_init(options)
         super(options)
-        ensure_index [[ geocoder_options[:coordinates], Mongo::GEO2D ]],
-          :min => -180, :max => 180 # create 2d index
+        if options[:skip_index] == false
+          ensure_index [[ geocoder_options[:coordinates], Mongo::GEO2D ]],
+            :min => -180, :max => 180 # create 2d index
+        end
       end
     end
   end
diff --git a/lib/geocoder/models/mongoid.rb b/lib/geocoder/models/mongoid.rb
index e3ca53a3254c38ca9145f1db221727a2727c5486..9e0b9fd832127dcf2439a06786d78658d7fc9e40 100644
--- a/lib/geocoder/models/mongoid.rb
+++ b/lib/geocoder/models/mongoid.rb
@@ -16,8 +16,16 @@ module Geocoder
 
       def geocoder_init(options)
         super(options)
-        index [[ geocoder_options[:coordinates], Mongo::GEO2D ]],
-          :min => -180, :max => 180 # create 2d index
+        if options[:skip_index] == false
+          # create 2d index
+          if (::Mongoid::VERSION >= "3")
+            index({ geocoder_options[:coordinates].to_sym => '2d' }, 
+                  {:min => -180, :max => 180})
+          else
+            index [[ geocoder_options[:coordinates], '2d' ]],
+              :min => -180, :max => 180
+          end
+        end
       end
     end
   end
diff --git a/lib/geocoder/results/base.rb b/lib/geocoder/results/base.rb
index 645e3c2a29e1400f4e25b567aaafed4eba3040de..8a42413f229dff258629fb64785518eee212f3e2 100644
--- a/lib/geocoder/results/base.rb
+++ b/lib/geocoder/results/base.rb
@@ -1,13 +1,14 @@
 module Geocoder
   module Result
     class Base
-      attr_accessor :data
+      attr_accessor :data, :cache_hit
 
       ##
       # Takes a hash of result data from a parsed Google result document.
       #
       def initialize(data)
         @data = data
+        @cache_hit = nil
       end
 
       ##
diff --git a/lib/geocoder/results/yandex.rb b/lib/geocoder/results/yandex.rb
index 841da9887e1c074699960caffa886b2ca0e76f70..bbcf9974b319374ffc368bfc584a873b9e2f51e3 100644
--- a/lib/geocoder/results/yandex.rb
+++ b/lib/geocoder/results/yandex.rb
@@ -57,6 +57,10 @@ module Geocoder::Result
       address_details['Locality']['Premise']['PremiseName']
     end
 
+    def precision
+      @data['GeoObject']['metaDataProperty']['GeocoderMetaData']['precision']
+    end
+
     private # ----------------------------------------------------------------
 
     def address_details
diff --git a/lib/geocoder/stores/active_record.rb b/lib/geocoder/stores/active_record.rb
index 819e987c4480e622f079ce599df26df26151d81e..782458f524372f95cd2ac9158dcec8115589e494 100644
--- a/lib/geocoder/stores/active_record.rb
+++ b/lib/geocoder/stores/active_record.rb
@@ -33,10 +33,10 @@ module Geocoder::Store
         #
         scope :near, lambda{ |location, *args|
           latitude, longitude = Geocoder::Calculations.extract_coordinates(location)
-          if latitude and longitude
+          if Geocoder::Calculations.coordinates_present?(latitude, longitude)
             near_scope_options(latitude, longitude, *args)
           else
-            where(:id => false) # no results if no lat/lon given
+            where(false_condition) # no results if no lat/lon given
           end
         }
 
@@ -49,7 +49,7 @@ module Geocoder::Store
         #
         scope :within_bounding_box, lambda{ |bounds|
           sw_lat, sw_lng, ne_lat, ne_lng = bounds.flatten if bounds
-          return where(:id => false) unless sw_lat && sw_lng && ne_lat && ne_lng
+          return where(false_condition) unless sw_lat && sw_lng && ne_lat && ne_lng
           spans = "#{geocoder_options[:latitude]} BETWEEN #{sw_lat} AND #{ne_lat} AND "
           spans << if sw_lng > ne_lng   # Handle a box that spans 180
             "#{geocoder_options[:longitude]} BETWEEN #{sw_lng} AND 180 OR #{geocoder_options[:longitude]} BETWEEN -180 AND #{ne_lng}"
@@ -68,29 +68,33 @@ module Geocoder::Store
 
       def distance_from_sql(location, *args)
         latitude, longitude = Geocoder::Calculations.extract_coordinates(location)
-        distance_from_sql_options(latitude, longitude, *args) if latitude and longitude
+        if Geocoder::Calculations.coordinates_present?(latitude, longitude)
+          distance_from_sql_options(latitude, longitude, *args)
+        end
       end
 
       private # ----------------------------------------------------------------
 
       ##
       # Get options hash suitable for passing to ActiveRecord.find to get
-      # records within a radius (in miles) of the given point.
+      # records within a radius (in kilometers) of the given point.
       # Options hash may include:
       #
-      # * +:units+   - <tt>:mi</tt> (default) or <tt>:km</tt>; to be used
+      # * +:units+   - <tt>:mi</tt> or <tt>:km</tt>; to be used.
       #   for interpreting radius as well as the +distance+ attribute which
-      #   is added to each found nearby object
-      # * +:bearing+ - <tt>:linear</tt> (default) or <tt>:spherical</tt>;
+      #   is added to each found nearby object.
+      #   See Geocoder::Configuration to know how configure default units.
+      # * +:bearing+ - <tt>:linear</tt> or <tt>:spherical</tt>.
       #   the method to be used for calculating the bearing (direction)
       #   between the given point and each found nearby point;
-      #   set to false for no bearing calculation
+      #   set to false for no bearing calculation.
+      #   See Geocoder::Configuration to know how configure default method.
       # * +:select+  - string with the SELECT SQL fragment (e.g. “id, name”)
       # * +:order+   - column(s) for ORDER BY SQL clause; default is distance
       # * +:exclude+ - an object to exclude (used by the +nearbys+ method)
       #
       def near_scope_options(latitude, longitude, radius = 20, options = {})
-        if connection.adapter_name.match /sqlite/i
+        if using_sqlite?
           approx_near_scope_options(latitude, longitude, radius, options)
         else
           full_near_scope_options(latitude, longitude, radius, options)
@@ -98,7 +102,7 @@ module Geocoder::Store
       end
 
       def distance_from_sql_options(latitude, longitude, options = {})
-        if connection.adapter_name.match /sqlite/i
+        if using_sqlite?
           approx_distance_from_sql(latitude, longitude, options)
         else
           full_distance_from_sql(latitude, longitude, options)
@@ -116,33 +120,35 @@ module Geocoder::Store
       def full_near_scope_options(latitude, longitude, radius, options)
         lat_attr = geocoder_options[:latitude]
         lon_attr = geocoder_options[:longitude]
-        options[:bearing] = :linear unless options.include?(:bearing)
+        options[:bearing] ||= (options[:method] ||
+                               geocoder_options[:method] ||
+                               Geocoder::Configuration.distances)
         bearing = case options[:bearing]
         when :linear
           "CAST(" +
             "DEGREES(ATAN2( " +
-              "RADIANS(#{lon_attr} - #{longitude}), " +
-              "RADIANS(#{lat_attr} - #{latitude})" +
+              "RADIANS(#{full_column_name(lon_attr)} - #{longitude}), " +
+              "RADIANS(#{full_column_name(lat_attr)} - #{latitude})" +
             ")) + 360 " +
           "AS decimal) % 360"
         when :spherical
           "CAST(" +
             "DEGREES(ATAN2( " +
-              "SIN(RADIANS(#{lon_attr} - #{longitude})) * " +
-              "COS(RADIANS(#{lat_attr})), (" +
-                "COS(RADIANS(#{latitude})) * SIN(RADIANS(#{lat_attr}))" +
+              "SIN(RADIANS(#{full_column_name(lon_attr)} - #{longitude})) * " +
+              "COS(RADIANS(#{full_column_name(lat_attr)})), (" +
+                "COS(RADIANS(#{latitude})) * SIN(RADIANS(#{full_column_name(lat_attr)}))" +
               ") - (" +
-                "SIN(RADIANS(#{latitude})) * COS(RADIANS(#{lat_attr})) * " +
-                "COS(RADIANS(#{lon_attr} - #{longitude}))" +
+                "SIN(RADIANS(#{latitude})) * COS(RADIANS(#{full_column_name(lat_attr)})) * " +
+                "COS(RADIANS(#{full_column_name(lon_attr)} - #{longitude}))" +
               ")" +
             ")) + 360 " +
           "AS decimal) % 360"
         end
-
+        options[:units] ||= (geocoder_options[:units] || Geocoder::Configuration.units)
         distance = full_distance_from_sql(latitude, longitude, options)
         conditions = ["#{distance} <= ?", radius]
         default_near_scope_options(latitude, longitude, radius, options).merge(
-          :select => "#{options[:select] || "#{table_name}.*"}, " +
+          :select => "#{options[:select] || full_column_name("*")}, " +
             "#{distance} AS distance" +
             (bearing ? ", #{bearing} AS bearing" : ""),
           :conditions => add_exclude_condition(conditions, options[:exclude])
@@ -160,9 +166,9 @@ module Geocoder::Store
         earth = Geocoder::Calculations.earth_radius(options[:units] || :mi)
 
         "#{earth} * 2 * ASIN(SQRT(" +
-          "POWER(SIN((#{latitude} - #{table_name}.#{lat_attr}) * PI() / 180 / 2), 2) + " +
-          "COS(#{latitude} * PI() / 180) * COS(#{table_name}.#{lat_attr} * PI() / 180) * " +
-          "POWER(SIN((#{longitude} - #{table_name}.#{lon_attr}) * PI() / 180 / 2), 2) ))"
+          "POWER(SIN((#{latitude} - #{full_column_name(lat_attr)}) * PI() / 180 / 2), 2) + " +
+          "COS(#{latitude} * PI() / 180) * COS(#{full_column_name(lat_attr)} * PI() / 180) * " +
+          "POWER(SIN((#{longitude} - #{full_column_name(lon_attr)}) * PI() / 180 / 2), 2) ))"
       end
 
       def approx_distance_from_sql(latitude, longitude, options)
@@ -175,8 +181,8 @@ module Geocoder::Store
         # sin of 45 degrees = average x or y component of vector
         factor = Math.sin(Math::PI / 4)
 
-        "(#{dy} * ABS(#{table_name}.#{lat_attr} - #{latitude}) * #{factor}) + " +
-          "(#{dx} * ABS(#{table_name}.#{lon_attr} - #{longitude}) * #{factor})"
+        "(#{dy} * ABS(#{full_column_name(lat_attr)} - #{latitude}) * #{factor}) + " +
+          "(#{dx} * ABS(#{full_column_name(lon_attr)} - #{longitude}) * #{factor})"
       end
 
       ##
@@ -191,27 +197,32 @@ module Geocoder::Store
       def approx_near_scope_options(latitude, longitude, radius, options)
         lat_attr = geocoder_options[:latitude]
         lon_attr = geocoder_options[:longitude]
-        options[:bearing] = :linear unless options.include?(:bearing)
+        unless options.include?(:bearing)
+          options[:bearing] = (options[:method] || \
+                               geocoder_options[:method] || \
+                               Geocoder::Configuration.distances)
+        end
         if options[:bearing]
           bearing = "CASE " +
-            "WHEN (#{lat_attr} >= #{latitude} AND #{lon_attr} >= #{longitude}) THEN  45.0 " +
-            "WHEN (#{lat_attr} <  #{latitude} AND #{lon_attr} >= #{longitude}) THEN 135.0 " +
-            "WHEN (#{lat_attr} <  #{latitude} AND #{lon_attr} <  #{longitude}) THEN 225.0 " +
-            "WHEN (#{lat_attr} >= #{latitude} AND #{lon_attr} <  #{longitude}) THEN 315.0 " +
+            "WHEN (#{full_column_name(lat_attr)} >= #{latitude} AND #{full_column_name(lon_attr)} >= #{longitude}) THEN  45.0 " +
+            "WHEN (#{full_column_name(lat_attr)} <  #{latitude} AND #{full_column_name(lon_attr)} >= #{longitude}) THEN 135.0 " +
+            "WHEN (#{full_column_name(lat_attr)} <  #{latitude} AND #{full_column_name(lon_attr)} <  #{longitude}) THEN 225.0 " +
+            "WHEN (#{full_column_name(lat_attr)} >= #{latitude} AND #{full_column_name(lon_attr)} <  #{longitude}) THEN 315.0 " +
           "END"
         else
           bearing = false
         end
 
         distance = approx_distance_from_sql(latitude, longitude, options)
+        options[:units] ||= (geocoder_options[:units] || Geocoder::Configuration.units)
 
         b = Geocoder::Calculations.bounding_box([latitude, longitude], radius, options)
         conditions = [
-          "#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] +
+          "#{full_column_name(lat_attr)} BETWEEN ? AND ? AND #{full_column_name(lon_attr)} BETWEEN ? AND ?"] +
           [b[0], b[2], b[1], b[3]
         ]
         default_near_scope_options(latitude, longitude, radius, options).merge(
-          :select => "#{options[:select] || "#{table_name}.*"}, " +
+          :select => "#{options[:select] || full_column_name("*")}, " +
             "#{distance} AS distance" +
             (bearing ? ", #{bearing} AS bearing" : ""),
           :conditions => add_exclude_condition(conditions, options[:exclude])
@@ -235,11 +246,30 @@ module Geocoder::Store
       #
       def add_exclude_condition(conditions, exclude)
         if exclude
-          conditions[0] << " AND #{table_name}.id != ?"
+          conditions[0] << " AND #{full_column_name(:id)} != ?"
           conditions << exclude.id
         end
         conditions
       end
+
+      def using_sqlite?
+        connection.adapter_name.match /sqlite/i
+      end
+
+      ##
+      # Value which can be passed to where() to produce no results.
+      #
+      def false_condition
+        using_sqlite? ? 0 : "false"
+      end
+
+      ##
+      # Prepend table name if column name doesn't already contain one.
+      #
+      def full_column_name(column)
+        column = column.to_s
+        column.include?(".") ? column : [table_name, column].join(".")
+      end
     end
 
     ##
@@ -278,3 +308,4 @@ module Geocoder::Store
     alias_method :fetch_address, :reverse_geocode
   end
 end
+
diff --git a/lib/geocoder/stores/base.rb b/lib/geocoder/stores/base.rb
index f7726c645153738566b4d8468e2e506720a6704b..a9d578f4f55ab521aa0074342f912bb694d9477f 100644
--- a/lib/geocoder/stores/base.rb
+++ b/lib/geocoder/stores/base.rb
@@ -20,9 +20,10 @@ module Geocoder
       # Calculate the distance from the object to an arbitrary point.
       # See Geocoder::Calculations.distance_between for ways of specifying
       # the point. Also takes a symbol specifying the units
-      # (:mi or :km; default is :mi).
+      # (:mi or :km; can be specified in Geocoder configuration).
       #
-      def distance_to(point, units = :mi)
+      def distance_to(point, units = nil)
+        units ||= self.class.geocoder_options[:units]
         return nil unless geocoded?
         Geocoder::Calculations.distance_between(
           to_coordinates, point, :units => units)
@@ -36,6 +37,7 @@ module Geocoder
       # ways of specifying the point.
       #
       def bearing_to(point, options = {})
+        options[:method] ||= self.class.geocoder_options[:method]
         return nil unless geocoded?
         Geocoder::Calculations.bearing_between(
           to_coordinates, point, options)
@@ -47,6 +49,7 @@ module Geocoder
       # ways of specifying the point.
       #
       def bearing_from(point, options = {})
+        options[:method] ||= self.class.geocoder_options[:method]
         return nil unless geocoded?
         Geocoder::Calculations.bearing_between(
           point, to_coordinates, options)
@@ -78,7 +81,6 @@ module Geocoder
         fail
       end
 
-
       private # --------------------------------------------------------------
 
       ##
@@ -114,3 +116,4 @@ module Geocoder
     end
   end
 end
+
diff --git a/lib/geocoder/stores/mongo_base.rb b/lib/geocoder/stores/mongo_base.rb
index 29054e486f25987c56cfa2dcda63d91c71bd6fc5..13ae12fd02dc5eebd08378a14b28a0440e958c43 100644
--- a/lib/geocoder/stores/mongo_base.rb
+++ b/lib/geocoder/stores/mongo_base.rb
@@ -20,6 +20,7 @@ module Geocoder::Store
 
           radius  = args.size > 0 ? args.shift : 20
           options = args.size > 0 ? args.shift : {}
+          options[:units] ||= geocoder_options[:units]
 
           # Use BSON::OrderedHash if Ruby's hashes are unordered.
           # Conditions must be in order required by indexes (see mongo gem).
@@ -30,7 +31,7 @@ module Geocoder::Store
           conds[field] = empty.clone
           conds[field]["$nearSphere"]  = coords.reverse
           conds[field]["$maxDistance"] = \
-            Geocoder::Calculations.distance_to_radians(radius, options[:units] || :mi)
+            Geocoder::Calculations.distance_to_radians(radius, options[:units])
 
           if obj = options[:exclude]
             conds[:_id.ne] = obj.id
@@ -81,3 +82,4 @@ module Geocoder::Store
     end
   end
 end
+
diff --git a/lib/geocoder/version.rb b/lib/geocoder/version.rb
index ef1e30beed4e1e726c0400949ebac4e75df50952..beb3d4f30633e6ce12db90b77a93841eaee27340 100644
--- a/lib/geocoder/version.rb
+++ b/lib/geocoder/version.rb
@@ -1,3 +1,3 @@
 module Geocoder
-  VERSION = "1.1.1"
+  VERSION = "1.1.2"
 end
diff --git a/lib/tasks/geocoder.rake b/lib/tasks/geocoder.rake
index f235e1b51b2cb047021042a5d4719f3e4233ab40..33ed4829e1ed76c624106d0fae5deefef82378f7 100644
--- a/lib/tasks/geocoder.rake
+++ b/lib/tasks/geocoder.rake
@@ -3,10 +3,23 @@ namespace :geocode do
   task :all => :environment do
     class_name = ENV['CLASS'] || ENV['class']
     raise "Please specify a CLASS (model)" unless class_name
-    klass = Object.const_get(class_name)
+    klass = class_from_string(class_name)
 
     klass.not_geocoded.each do |obj|
       obj.geocode; obj.save
     end
   end
 end
+
+##
+# Get a class object from the string given in the shell environment.
+# Similar to ActiveSupport's +constantize+ method.
+#
+def class_from_string(class_name)
+  parts = class_name.split("::")
+  constant = Object
+  parts.each do |part|
+    constant = constant.const_get(part)
+  end
+  constant
+end
diff --git a/test/calculations_test.rb b/test/calculations_test.rb
index 25343cb7a5f3ae3f53153e9bf3fafe57fa1bcdde..4f9fef0df46df8131fb82d67bd7f9b93e61f68d8 100644
--- a/test/calculations_test.rb
+++ b/test/calculations_test.rb
@@ -2,7 +2,12 @@
 require 'test_helper'
 
 class CalculationsTest < Test::Unit::TestCase
-
+  def setup
+    Geocoder.configure do |config|
+      config.units  = :mi
+      config.distances = :linear
+    end
+  end
 
   # --- degree distance ---
 
@@ -144,4 +149,40 @@ class CalculationsTest < Test::Unit::TestCase
     l = Landmark.new(*landmark_params(:msg))
     assert_equal l.bearing_from([50,-86.1]), l.bearing_to([50,-86.1]) - 180
   end
+
+  def test_extract_coordinates
+    result = Geocoder::Calculations.extract_coordinates([ nil, nil ])
+    assert is_nan_coordinates?(result)
+
+    result = Geocoder::Calculations.extract_coordinates([ 1.0 / 3, 2.0 / 3 ])
+    assert_in_delta 1.0 / 3, result.first, 1E-5
+    assert_in_delta 2.0 / 3, result.last, 1E-5
+
+    result = Geocoder::Calculations.extract_coordinates(nil)
+    assert is_nan_coordinates?(result)
+
+    result = Geocoder::Calculations.extract_coordinates('')
+    assert is_nan_coordinates?(result)
+
+    result = Geocoder::Calculations.extract_coordinates([ 'nix' ])
+    assert is_nan_coordinates?(result)
+
+    o = Object.new
+    result = Geocoder::Calculations.extract_coordinates(o)
+    assert is_nan_coordinates?(result)
+
+    def o.to_coordinates
+      [ 1.0 / 3, 2.0 / 3 ]
+    end
+    result = Geocoder::Calculations.extract_coordinates(o)
+    assert_in_delta 1.0 / 3, result.first, 1E-5
+    assert_in_delta 2.0 / 3, result.last, 1E-5
+  end
+
+  def test_coordinates_present
+    assert Geocoder::Calculations.coordinates_present?(3.23)
+    assert !Geocoder::Calculations.coordinates_present?(nil)
+    assert !Geocoder::Calculations.coordinates_present?(Geocoder::Calculations::NAN)
+    assert !Geocoder::Calculations.coordinates_present?(3.23, nil)
+  end
 end
diff --git a/test/configuration_test.rb b/test/configuration_test.rb
index 4c4e668186218874e10611f24cd2f899f667ab79..4137fbf44bf2a8fc6f7e8561f17234944f70e107 100644
--- a/test/configuration_test.rb
+++ b/test/configuration_test.rb
@@ -2,6 +2,9 @@
 require 'test_helper'
 
 class ConfigurationTest < Test::Unit::TestCase
+  def setup
+    Geocoder::Configuration.set_defaults
+  end
 
   def test_exception_raised_on_bad_lookup_config
     Geocoder::Configuration.lookup = :stoopid
@@ -10,4 +13,91 @@ class ConfigurationTest < Test::Unit::TestCase
     end
   end
 
+  # --- class method configuration ---
+  def test_configurated_by_class_method
+    Geocoder::Configuration.units = :mi
+    distance = Geocoder::Calculations.distance_between([0,0], [0,1]).round
+    assert_not_equal 111, distance
+    assert_equal      69, distance
+
+    Geocoder::Configuration.units = :km
+    distance = Geocoder::Calculations.distance_between([0,0], [0,1]).round
+    assert_equal    111, distance
+    assert_not_equal 69, distance
+
+    Geocoder::Configuration.distances = :spherical
+    angle = Geocoder::Calculations.bearing_between([50,-85], [40.750354, -73.993371]).round
+    assert_equal     136, angle
+    assert_not_equal 130, angle
+
+    Geocoder::Configuration.distances = :linear
+    angle = Geocoder::Calculations.bearing_between([50,-85], [40.750354, -73.993371]).round
+    assert_not_equal 136, angle
+    assert_equal     130, angle
+  end
+
+  # --- Geocoder#configure distances configuration ---
+  def test_geocoder_configuration
+    # DSL
+    Geocoder.configure do |config|
+      config.units  = :mi
+      config.distances = :linear
+    end
+
+    assert_equal Geocoder::Configuration.units, :mi
+    distance = Geocoder::Calculations.distance_between([0,0], [0,1]).round
+    assert_not_equal 111, distance
+    assert_equal      69, distance
+
+    assert_equal Geocoder::Configuration.distances, :linear
+    angle = Geocoder::Calculations.bearing_between([50,-85], [40.750354, -73.993371]).round
+    assert_not_equal 136, angle
+    assert_equal     130, angle
+
+    # Direct
+    Geocoder.configure.units  = :km
+    Geocoder.configure.distances = :spherical
+
+    assert_equal Geocoder::Configuration.units, :km
+    distance = Geocoder::Calculations.distance_between([0,0], [0,1]).round
+    assert_equal    111, distance
+    assert_not_equal 69, distance
+
+    assert_equal Geocoder::Configuration.distances, :spherical
+    angle = Geocoder::Calculations.bearing_between([50,-85], [40.750354, -73.993371]).round
+    assert_equal     136, angle
+    assert_not_equal 130, angle
+  end
+
+  # Geocoder per-model configuration
+  def test_model_configuration
+    Landmark.reverse_geocoded_by :latitude, :longitude, :method => :spherical, :units => :km
+    assert_equal :km,        Landmark.geocoder_options[:units]
+    assert_equal :spherical, Landmark.geocoder_options[:method]
+
+    v = Landmark.new(*landmark_params(:msg))
+    v.latitude  = 0
+    v.longitude = 0
+    assert_equal 111, v.distance_to([0,1]).round
+    v.latitude  = 40.750354
+    v.longitude = -73.993371
+    assert_equal 136, v.bearing_from([50,-85]).round
+  end
+
+  def test_configuration_chain
+    v = Landmark.new(*landmark_params(:msg))
+    v.latitude  = 0
+    v.longitude = 0
+
+    # method option > global configuration
+    Geocoder.configure.units  = :km
+    assert_equal 69, v.distance_to([0,1], :mi).round
+
+    # per-model configuration > global configuration
+    Landmark.reverse_geocoded_by :latitude, :longitude, :method => :spherical, :units => :mi
+    assert_equal 69, v.distance_to([0,1]).round
+
+    # method option > per-model configuration
+    assert_equal 111, v.distance_to([0,1], :km).round
+  end
 end
diff --git a/test/custom_block_test.rb b/test/custom_block_test.rb
index 8fab62e819aa6ff05a1b706e185ab7aba92008fc..0f4789d163dc80ab40016016571848f623525499 100644
--- a/test/custom_block_test.rb
+++ b/test/custom_block_test.rb
@@ -29,3 +29,4 @@ class CustomBlockTest < Test::Unit::TestCase
     assert_nil e.address
   end
 end
+
diff --git a/test/input_handling_test.rb b/test/input_handling_test.rb
index 9d453b97b562c615bc82178495dba36c05e9d9a7..f5da1f13c9df941fdbf08a157464a0dbb0738d7c 100644
--- a/test/input_handling_test.rb
+++ b/test/input_handling_test.rb
@@ -6,8 +6,10 @@ class InputHandlingTest < Test::Unit::TestCase
   def test_ip_address_detection
     assert Geocoder.send(:ip_address?, "232.65.123.94")
     assert Geocoder.send(:ip_address?, "666.65.123.94") # technically invalid
+    assert Geocoder.send(:ip_address?, "::ffff:12.34.56.78")
     assert !Geocoder.send(:ip_address?, "232.65.123.94.43")
     assert !Geocoder.send(:ip_address?, "232.65.123")
+    assert !Geocoder.send(:ip_address?, "::ffff:123.456.789")
   end
 
   def test_blank_query_detection
diff --git a/test/lookup_test.rb b/test/lookup_test.rb
index 3c72d05b84294fce0a7ce0394ee9645d649edf81..0b627c71cd8f4ed12cf878b837b838a8e19b1bc2 100644
--- a/test/lookup_test.rb
+++ b/test/lookup_test.rb
@@ -27,4 +27,11 @@ class LookupTest < Test::Unit::TestCase
     g = Geocoder::Lookup::Yahoo.new
     assert_match "appid=MY_KEY", g.send(:query_url, "Madison Square Garden, New York, NY  10001, United States")
   end
+
+  def test_geocoder_ca_showpostal
+    Geocoder::Configuration.api_key = "MY_KEY"
+    g = Geocoder::Lookup::GeocoderCa.new
+    assert_match "showpostal=1", g.send(:query_url, "Madison Square Garden, New York, NY  10001, United States")
+  end
+
 end
diff --git a/test/mongoid_test.rb b/test/mongoid_test.rb
index 44b4ca9a0798538974177cfb79332657d9908e3b..1af5e9cd56e64d617b0e0fcee676de9b14925e16 100644
--- a/test/mongoid_test.rb
+++ b/test/mongoid_test.rb
@@ -1,12 +1,7 @@
 # encoding: utf-8
-require 'test_helper'
-
-begin
-require 'mongoid'
 require 'mongoid_test_helper'
 
 class MongoidTest < Test::Unit::TestCase
-
   def test_geocoded_check
     p = Place.new(*venue_params(:msg))
     p.location = [40.750354, -73.993371]
@@ -22,10 +17,23 @@ class MongoidTest < Test::Unit::TestCase
   def test_custom_coordinate_field_near_scope
     location = [40.750354, -73.993371]
     p = Place.near(location)
-    assert_equal p.selector[:location]['$nearSphere'], location.reverse
+    key = Mongoid::VERSION >= "3" ? "location" : :location
+    assert_equal p.selector[key]['$nearSphere'], location.reverse
   end
-end
 
-rescue LoadError => crash
-  warn 'Mongoid not installed, not tested.'
+  def test_model_configuration
+    p = Place.new(*venue_params(:msg))
+    p.location = [0, 0]
+
+    Place.geocoded_by :address, :coordinates => :location, :units => :km
+    assert_equal 111, p.distance_to([0,1]).round
+
+    Place.geocoded_by :address, :coordinates => :location, :units => :mi
+    assert_equal 69, p.distance_to([0,1]).round
+  end
+
+  def test_index_is_skipped_if_skip_option_flag
+    result = PlaceWithoutIndex.index_options.keys.flatten[0] == :coordinates
+    assert !result
+  end
 end
diff --git a/test/mongoid_test_helper.rb b/test/mongoid_test_helper.rb
index 69eb2fd044c593898780e3e73fb2f8463905e207..cf37bb01c236fb9b6df27b81f39bcbed5884e1a2 100644
--- a/test/mongoid_test_helper.rb
+++ b/test/mongoid_test_helper.rb
@@ -1,11 +1,18 @@
 require 'rubygems'
 require 'test/unit'
+require 'test_helper'
+require 'mongoid'
+require 'geocoder/models/mongoid'
 
 $LOAD_PATH.unshift(File.dirname(__FILE__))
 $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
 
-Mongoid.configure do |config|
-  config.logger = Logger.new($stderr, :debug)
+if (::Mongoid::VERSION >= "3")
+  Mongoid.logger = Logger.new($stderr, :debug)
+else
+  Mongoid.configure do |config|
+    config.logger = Logger.new($stderr, :debug)
+  end
 end
 
 ##
@@ -26,3 +33,11 @@ class Place
     write_attribute :address, address
   end
 end
+
+class PlaceWithoutIndex
+  include Mongoid::Document
+  include Geocoder::Model::Mongoid
+
+  field :location, :type => Array
+  geocoded_by :location, :skip_index => true
+end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index d34b63c0359256e40432bea7c691d83042dc94ad..61b1d058fdf2e6031d4c1087b5b62e2173f50d2f 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -150,7 +150,7 @@ module Geocoder
       end
     end
 
-  class Nominatim < Base
+    class Nominatim < Base
       private #-----------------------------------------------------------------
       def fetch_raw_data(query, reverse = false)
         raise TimeoutError if query == "timeout"
@@ -271,4 +271,11 @@ class Test::Unit::TestCase
   def street_lookups
     all_lookups - [:freegeoip]
   end
+
+  def is_nan_coordinates?(coordinates)
+    return false unless coordinates.respond_to? :size # Should be an array
+    return false unless coordinates.size == 2 # Should have dimension 2
+    coordinates[0].nan? && coordinates[1].nan? # Both coordinates should be NaN
+  end
 end
+