rails-geocoder 0.8.7 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Per-release changes to Geocoder.
4
4
 
5
+ == 0.8.8 (2009 Dec 7)
6
+
7
+ * Automatically select a less accurate but compatible distance algorithm when SQLite database detected (fixes SQLite incompatibility).
8
+
5
9
  == 0.8.7 (2009 Nov 4)
6
10
 
7
11
  * Added Geocoder.geographic_center method.
data/README.rdoc CHANGED
@@ -102,6 +102,24 @@ If your model has +address+, +city+, +state+, and +country+ attributes you might
102
102
  Please see the code for more methods and detailed information about arguments (eg, working with kilometers).
103
103
 
104
104
 
105
+ == SQLite
106
+
107
+ SQLite's lack of trigonometric functions means Geocoder's default implementation of the +near+ method (named scope) does not work. When using SQLite, Geocoder will automatically use a less accurate algorithm for finding objects near a given point. Results of this algorithm should not be trusted too much as it will return objects that are outside the given radius.
108
+
109
+
110
+ === Discussion
111
+
112
+ There are few options for finding objects near a given point in SQLite without installing extensions:
113
+
114
+ 1. Use a square instead of a circle for finding nearby points. For example, if you want to find points near 40.71, 100.23, search for objects with latitude between 39.71 and 41.71 and longitude between 99.23 and 101.23. One degree of latitude or longitude is at most 69 miles so divide your radius (in miles) by 69.0 to get the amount to add and subtract from your center coordinates to get the upper and lower bounds. The results will not be very accurate (you'll get points outside the desired radius), but you will get all the points within the required radius.
115
+
116
+ 2. Load all objects into memory and compute distances between them using the <tt>Geocoder.distance_between</tt> method. This will produce accurate results but will be very slow (and use a lot of memory) if you have a lot of objects in your database.
117
+
118
+ 3. If you have a large number of objects (so you can't use approach #2) and you need accurate results (better than approach #1 will give), you can use a combination of the two. Get all the objects within a square around your center point, and then eliminate the ones that are too far away using <tt>Geocoder.distance_between</tt>.
119
+
120
+ Because Geocoder needs to provide this functionality as a named scope, we must go with option #1, but feel free to implement #2 or #3 if you need more accuracy.
121
+
122
+
105
123
  == To-do List
106
124
 
107
125
  * <tt>install.rb</tt> should do some setup when installed as a plugin
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.7
1
+ 0.8.8
data/lib/geocoder.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'rexml/document'
2
+
1
3
  ##
2
4
  # Add geocoding functionality (via Google) to any object.
3
5
  #
@@ -42,21 +44,9 @@ module Geocoder
42
44
  #
43
45
  module ClassMethods
44
46
 
45
- ##
46
- # DEPRECATED: Please use the +near+ method/named scope instead.
47
- #
48
- def find_near(location, radius = 20, options = {})
49
- warn "Geocoder deprecation warning: the 'find_near' class method is " +
50
- "deprecated, please use the 'near' method, which is a named scope."
51
- near(location, radius, options)
52
- end
53
-
54
47
  ##
55
48
  # Get options hash suitable for passing to ActiveRecord.find to get
56
49
  # records within a radius (in miles) of the given point.
57
- # Taken from excellent tutorial at:
58
- # http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL
59
- #
60
50
  # Options hash may include:
61
51
  #
62
52
  # +order+ :: column(s) for ORDER BY SQL clause
@@ -64,6 +54,24 @@ module Geocoder
64
54
  # +offset+ :: number of records to skip (for LIMIT SQL clause)
65
55
  #
66
56
  def near_scope_options(latitude, longitude, radius = 20, options = {})
57
+ if ActiveRecord::Base.connection.adapter_name == "SQLite"
58
+ approx_near_scope_options(latitude, longitude, radius, options)
59
+ else
60
+ full_near_scope_options(latitude, longitude, radius, options)
61
+ end
62
+ end
63
+
64
+
65
+ private # ----------------------------------------------------------------
66
+
67
+ ##
68
+ # Named scope options hash for use with a database that supports POWER(),
69
+ # SQRT(), PI(), and trigonometric functions (SIN(), COS(), and ASIN()).
70
+ #
71
+ # Taken from the excellent tutorial at:
72
+ # http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL
73
+ #
74
+ def full_near_scope_options(latitude, longitude, radius, options)
67
75
 
68
76
  # set defaults/clean up arguments
69
77
  options[:order] ||= 'distance ASC'
@@ -102,6 +110,44 @@ module Geocoder
102
110
  :limit => limit
103
111
  }
104
112
  end
113
+
114
+ ##
115
+ # Named scope options hash for use with a database without trigonometric
116
+ # functions, like SQLite. Approach is to find objects within a square
117
+ # rather than a circle, so results are very approximate (will include
118
+ # objects outside the given radius).
119
+ #
120
+ def approx_near_scope_options(latitude, longitude, radius, options)
121
+
122
+ # set defaults/clean up arguments
123
+ radius = radius.to_i
124
+
125
+ # constrain search to a (radius x radius) square
126
+ factor = (Math::cos(latitude * Math::PI / 180.0) * 69.0).abs
127
+ lon_lo = longitude - (radius / factor);
128
+ lon_hi = longitude + (radius / factor);
129
+ lat_lo = latitude - (radius / 69.0);
130
+ lat_hi = latitude + (radius / 69.0);
131
+
132
+ # build limit clause
133
+ limit = nil
134
+ if options[:limit] or options[:offset]
135
+ options[:offset] ||= 0
136
+ limit = "#{options[:offset]},#{options[:limit]}"
137
+ end
138
+
139
+ # generate hash
140
+ lat_attr = geocoder_options[:latitude]
141
+ lon_attr = geocoder_options[:longitude]
142
+ {
143
+ :conditions => [
144
+ "#{lat_attr} BETWEEN ? AND ? AND " +
145
+ "#{lon_attr} BETWEEN ? AND ?",
146
+ lat_lo, lat_hi, lon_lo, lon_hi],
147
+ :order => options[:order],
148
+ :limit => limit
149
+ }
150
+ end
105
151
  end
106
152
 
107
153
  ##
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rails-geocoder}
8
- s.version = "0.8.7"
8
+ s.version = "0.8.8"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Alex Reisner"]
12
- s.date = %q{2009-11-04}
12
+ s.date = %q{2009-12-07}
13
13
  s.description = %q{Geocoder adds object geocoding and database-agnostic distance calculations to Ruby on Rails. It does not rely on proprietary database functions so finding geocoded objects in a given area is easily done using out-of-the-box MySQL or even SQLite.}
14
14
  s.email = %q{alex@alexreisner.com}
15
15
  s.extra_rdoc_files = [
@@ -52,3 +52,4 @@ Gem::Specification.new do |s|
52
52
  else
53
53
  end
54
54
  end
55
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-geocoder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.7
4
+ version: 0.8.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Reisner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-04 00:00:00 -05:00
12
+ date: 2009-12-07 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15