Skip to content
Snippets Groups Projects
Commit 2b69ba59 authored by Alex Reisner's avatar Alex Reisner
Browse files

Remove Rails 2-specific code.

Stop allowing full :conditions option to near_scope_options (was
deprecated, now it's gone). Update installation documentation.
parent 3b53f0ee
No related branches found
Tags 1.1.8
No related merge requests found
......@@ -2,6 +2,12 @@
Per-release changes to Geocoder.
== 0.9.5 (TBA)
* Don't allow :conditions hash in 'options' argument to 'nearbys' method (was deprecated in 0.9.3).
* Separate Rails 2 and Rails 3-compatible branches.
* Switch from Google's XML to JSON geocoding API.
== 0.9.4 (2010 Aug 2)
* Google Maps API key no longer required (uses geocoder v3).
......
......@@ -2,27 +2,12 @@
Geocoder adds object geocoding and database-agnostic distance calculations to Ruby on Rails. It's as simple as calling <tt>fetch_coordinates!</tt> on your objects, and then using a scope like <tt>Venue.near("Billings, MT")</tt>. Since it does not rely on proprietary database functions finding geocoded objects in a given area works with out-of-the-box MySQL or even SQLite.
<b>Geocoder is currently compatible with Rails 2.x and Rails 3.</b> Also, a Google Maps API key is no longer necessary.
<b>Geocoder is compatible with Rails 2 (see the rails2 branch) and Rails 3.</b>
== 1. Install
=== a. Rails 2
Install either as a plugin:
script/plugin install git://github.com/alexreisner/geocoder.git
or as a gem:
# add to config/environment.rb:
config.gem "rails-geocoder", :lib => "geocoder", :source => "http://gemcutter.org/"
# at command prompt:
sudo rake gems:install
=== b. Rails 3
=== a. Rails 3
Install either as a plugin:
......@@ -32,11 +17,18 @@ or as a gem:
# add to Gemfile:
gem "rails-geocoder", :require => "geocoder"
# at command prompt:
bundle install
=== b. Rails 2
Install as a plugin from the rails2 branch:
script/plugin install git://github.com/alexreisner/geocoder.git -r rails2
== 2. Configure
A) Add +latitude+ and +longitude+ columns to your model:
......@@ -82,10 +74,10 @@ Some utility methods are also available:
# distance (in miles) between Eiffel Tower and Empire State Building
Geocoder.distance_between( 48.858205,2.294359, 40.748433,-73.985655 )
# look up coordinates of some location (like searching Google Maps)
Geocoder.fetch_coordinates("25 Main St, Cooperstown, NY")
# find the geographic center (aka center of gravity) of objects or points
Geocoder.geographic_center([ city1, city2, city3, [40.22,-73.99], city4 ])
......@@ -144,12 +136,20 @@ If anyone has a more elegant solution to this problem I am very interested in se
== To-do List
* fix Postgres problem (http://github.com/alexreisner/geocoder/issues#issue/5)
* use completely separate "drivers" for different AR adapters?
* seems reasonable since we're using very DB-specific features
* also need to make sure 'mysql2' is supported
* add reverse geocoding
* restructure as Railtie
* http://www.igvita.com/2010/08/04/rails-3-internals-railtie-creating-plugins/
* make 'near' scope work with 'select' options
* make 'near' scope work with AR associations
* http://stackoverflow.com/questions/3266358/geocoder-rails-plugin-near-search-problem-with-activerecord
* prepend table names to column names in SQL distance expression (required
to do joins on another geocoded model)
* unobtrusively add ability to get a result with more data (Geocoder object?)
* the default usage should remain dead simple
Copyright (c) 2009-10 Alex Reisner, released under the MIT license
......@@ -11,21 +11,21 @@ module Geocoder
base.class_eval do
# scope: geocoded objects
send(Geocoder.scope_method_name, :geocoded,
scope :geocoded,
:conditions => "#{geocoder_options[:latitude]} IS NOT NULL " +
"AND #{geocoder_options[:longitude]} IS NOT NULL")
"AND #{geocoder_options[:longitude]} IS NOT NULL"
# scope: not-geocoded objects
send(Geocoder.scope_method_name, :not_geocoded,
scope :not_geocoded,
:conditions => "#{geocoder_options[:latitude]} IS NULL " +
"OR #{geocoder_options[:longitude]} IS NULL")
"OR #{geocoder_options[:longitude]} IS NULL"
##
# Find all objects within a radius (in miles) of the given location
# (address string). Location (the first argument) may be either a string
# to geocode or an array of coordinates (<tt>[lat,long]</tt>).
#
send(Geocoder.scope_method_name, :near, lambda{ |location, *args|
scope :near, lambda{ |location, *args|
latitude, longitude = location.is_a?(Array) ?
location : Geocoder.fetch_coordinates(location)
if latitude and longitude
......@@ -33,7 +33,7 @@ module Geocoder
else
{}
end
})
}
end
end
......@@ -47,11 +47,12 @@ module Geocoder
# records within a radius (in miles) of the given point.
# Options hash may include:
#
# +units+ :: <tt>:mi</tt> (default) or <tt>:km</tt>
# +order+ :: column(s) for ORDER BY SQL clause
# +limit+ :: number of records to return (for LIMIT SQL clause)
# +offset+ :: number of records to skip (for OFFSET SQL clause)
# +select+ :: string with the SELECT SQL fragment (e.g. “id, name”)
# +units+ :: <tt>:mi</tt> (default) or <tt>:km</tt>
# +exclude+ :: exclude the given object (used by the #nearbys method)
# +order+ :: column(s) for ORDER BY SQL clause
# +limit+ :: number of records to return (for LIMIT SQL clause)
# +offset+ :: number of records to skip (for OFFSET SQL clause)
# +select+ :: string with the SELECT SQL fragment (e.g. “id, name”)
#
def near_scope_options(latitude, longitude, radius = 20, options = {})
radius *= km_in_mi if options[:units] == :km
......@@ -109,24 +110,11 @@ module Geocoder
conditions = \
["#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] +
coordinate_bounds(latitude, longitude, radius)
# Handle conditions. Passing of conditions by developers is deprecated
# but we will still need to handle conditions so, for example, we can
# exclude objects by ID from the nearbys method. This is incredibly
# ugly and doesn't work for a conditions hash: try using Arel?
if options[:conditions].is_a?(String)
options[:conditions] = [options[:conditions]]
end
if options[:conditions].is_a?(Array)
conditions[0] = "(#{conditions[0]}) AND #{options[:conditions][0]}"
conditions << options[:conditions][1]
end
{
:order => options[:order],
:limit => options[:limit],
:offset => options[:offset],
:conditions => conditions
:conditions => (obj = options[:exclude]) ? ["id != ?", obj.id] : nil
}
end
......@@ -184,21 +172,8 @@ module Geocoder
# Valid units are defined in <tt>distance_between</tt> class method.
#
def nearbys(radius = 20, units = :mi)
options = {:conditions => ["id != ?", id]}
if units.is_a? Hash
warn "DEPRECATION WARNING: The 'options' argument to the nearbys " +
"method is deprecated and will be removed from rails-geocoder in " +
"a future version. The second argument is now called 'units' and " +
"should be a symbol (:mi or :km, :mi is the default). The 'nearbys' " +
"method now returns a Rails 3 scope so you should specify more " +
"scopes and/or conditions via chaining. For example: " +
"city.nearbys(20).order('name').limit(10). Support for Rails 2.x " +
"will eventually be discontinued."
options.reverse_merge!(units)
else
options.reverse_merge!(:units => units)
end
return [] unless geocoded?
options = {:exclude => self, :units => units}
self.class.near(read_coordinates, radius, options)
end
......@@ -314,7 +289,7 @@ module Geocoder
#
def self.search(query)
doc = _fetch_parsed_response(query)
doc['status'] == "OK" ? doc : nil
doc && doc['status'] == "OK" ? doc : nil
end
##
......@@ -359,17 +334,6 @@ module Geocoder
return nil
end
end
##
# Name of the ActiveRecord scope method.
#
def self.scope_method_name
begin
Rails.version.starts_with?("3") ? :scope : :named_scope
rescue NameError
:named_scope
end
end
end
##
......
......@@ -27,7 +27,7 @@ module ActiveRecord
write_attribute(attr_name.to_sym, value)
end
def self.named_scope(*args); end
def self.scope(*args); end
end
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment