rails-geocoder 0.8.5 → 0.8.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  Per-release changes to Geocoder.
4
4
 
5
+ == 0.8.6 (2009 Oct 27)
6
+
7
+ * The fetch_coordinates method now assigns coordinates to attributes (behaves like fetch_coordinates! used to) and fetch_coordinates! both assigns and saves the attributes.
8
+ * Added geocode:all rake task.
9
+
5
10
  == 0.8.5 (2009 Oct 26)
6
11
 
7
12
  * Avoid calling deprecated method from within Geocoder itself.
data/README.rdoc CHANGED
@@ -1,6 +1,9 @@
1
1
  = Geocoder
2
2
 
3
- 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.
3
+ 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 named scope like <tt>Venue.near("Billings, MT")</tt>.
4
+
5
+ Geocoder 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.
6
+
4
7
 
5
8
  == 1. Install
6
9
 
@@ -16,51 +19,53 @@ or as a gem:
16
19
  # at command prompt:
17
20
  sudo rake gems:install
18
21
 
22
+
19
23
  == 2. Configure
20
24
 
21
- First, you must get a Google Maps API key (to get one go to http://code.google.com/apis/maps/signup.html) and store it in a constant:
25
+ A) Get a Google Maps API key (see http://code.google.com/apis/maps/signup.html) and store it in a constant:
22
26
 
27
+ # eg, in config/initializers/google_maps.rb
23
28
  GOOGLE_MAPS_API_KEY = "..."
24
29
 
25
- To add geocoding features to a class:
30
+ B) Add +latitude+ and +longitude+ columns to your model:
26
31
 
27
- geocoded_by :location
32
+ script/generate migration AddLatitudeAndLongitudeToYourModel latitude:float longitude:float
33
+ rake db:migrate
28
34
 
29
- Be sure your class defines attributes for storing latitude and longitude (use +float+ or +double+ database columns) and a location (human-readable address to be geocoded). These attribute names are all configurable; for example, to use +address+, +lat+, and +lon+ respectively:
35
+ C) Tell geocoder where your model stores its address:
30
36
 
31
- geocoded_by :address, :latitude => :lat, :longitude => :lon
37
+ geocoded_by :address
32
38
 
33
- A geocodable string is anything you'd use to search Google Maps. Any of the following are acceptable:
39
+ D) Optionally, auto-fetch coordinates every time your model is saved:
34
40
 
35
- 714 Green St, Big Town, MO
36
- Eiffel Tower, Paris, FR
37
- Paris, TX, US
41
+ after_validation :fetch_coordinates
38
42
 
39
- If your model has +address+, +city+, +state+, and +country+ attributes your +location+ method might look something like this:
43
+ <i>Note that you are not stuck with the +latitude+ and +longitude+ column names, or the +address+ method. See "More On Configuration" below for details.</i>
40
44
 
41
- def location
42
- [address, city, state, country].compact.join(', ')
43
- end
44
45
 
45
46
  == 3. Use
46
47
 
47
- Assuming +Venue+ is a geocoded model, it has the following named scopes:
48
+ Assuming +obj+ is an instance of a geocoded class, you can get its coordinates:
48
49
 
49
- Venue.near('Omaha, NE, US', 20) # venues within 20 miles of Omaha
50
- Venue.near([40.71, 100.23], 20) # venues within 20 miles of a point
51
- Venue.geocoded # venues with coordinates
52
- Venue.not_geocoded # venues without coordinates
50
+ obj.fetch_coordinates # fetches and assigns coordinates
51
+ obj.fetch_coordinates! # also saves lat, lon attributes
53
52
 
54
- Assuming +obj+ has a valid string for its +location+:
53
+ If you have a lot of objects you can use this Rake task to geocode them all:
55
54
 
56
- obj.fetch_coordinates # returns coordinates [lat, lon]
57
- obj.fetch_coordinates! # also writes coordinates to object
55
+ rake geocode:all CLASS=YourModel
58
56
 
59
- Assuming +obj+ is geocoded (has latitude and longitude):
57
+ Once +obj+ is geocoded you can do things like this:
60
58
 
61
59
  obj.nearbys(30) # other objects within 30 miles
62
60
  obj.distance_to(40.714, -100.234) # distance to arbitrary point
63
61
 
62
+ To find objects by location, use the following named scopes:
63
+
64
+ Venue.near('Omaha, NE, US', 20) # venues within 20 miles of Omaha
65
+ Venue.near([40.71, 100.23], 20) # venues within 20 miles of a point
66
+ Venue.geocoded # venues with coordinates
67
+ Venue.not_geocoded # venues without coordinates
68
+
64
69
  Some utility methods are also available:
65
70
 
66
71
  # distance (in miles) between Eiffel Tower and Empire State Building
@@ -70,7 +75,33 @@ Some utility methods are also available:
70
75
  Geocoder.fetch_coordinates("25 Main St, Cooperstown, NY")
71
76
 
72
77
 
78
+ == More On Configuration
79
+
80
+ You are not stuck with using the +latitude+ and +longitude+ database column names for storing coordinates. For example, to use +lat+ and +lon+:
81
+
82
+ geocoded_by :address, :latitude => :lat, :longitude => :lon
83
+
84
+ The string to use for geocoding can be anything you'd use to search Google Maps. For example, any of the following are acceptable:
85
+
86
+ 714 Green St, Big Town, MO
87
+ Eiffel Tower, Paris, FR
88
+ Paris, TX, US
89
+
90
+ If your model has +address+, +city+, +state+, and +country+ attributes you might do something like this:
91
+
92
+ geocoded_by :location
93
+
94
+ def location
95
+ [address, city, state, country].compact.join(', ')
96
+ end
97
+
98
+
73
99
  Please see the code for more methods and detailed information about arguments (eg, working with kilometers).
74
100
 
75
-
101
+
102
+ == To-do List
103
+
104
+ * <tt>install.rb</tt> should do some setup when installed as a plugin
105
+
106
+
76
107
  Copyright (c) 2009 Alex Reisner, released under the MIT license
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.5
1
+ 0.8.6
data/lib/geocoder.rb CHANGED
@@ -121,8 +121,8 @@ module Geocoder
121
121
  end
122
122
 
123
123
  ##
124
- # Calculate the distance from the object to a point (lat,lon). Valid units
125
- # are defined in <tt>distance_between</tt> class method.
124
+ # Calculate the distance from the object to a point (lat,lon).
125
+ # Valid units are defined in <tt>distance_between</tt> class method.
126
126
  #
127
127
  def distance_to(lat, lon, units = :mi)
128
128
  return nil unless geocoded?
@@ -131,34 +131,37 @@ module Geocoder
131
131
  end
132
132
 
133
133
  ##
134
- # Get other geocoded objects within a given radius.
135
- # The object must be geocoded before this method is called.
134
+ # Get other geocoded objects within a given radius (in miles). Takes a
135
+ # radius (in miles) and options for passing to the +near+ named scope
136
+ # (<tt>:order</tt>, <tt>:limit</tt>, and <tt>:offset</tt>).
136
137
  #
137
- def nearbys(radius = 20)
138
+ def nearbys(radius = 20, options = {})
138
139
  return [] unless geocoded?
139
- lat,lon = self.class._get_coordinates(self)
140
- self.class.near([lat, lon], radius) - [self]
140
+ coords = self.class._get_coordinates(self)
141
+ options = {:conditions => ["id != ?", id]}.merge(options)
142
+ self.class.near(coords, radius, options) - [self]
141
143
  end
142
144
 
143
145
  ##
144
- # Fetch coordinates based on the object's location.
145
- # Returns an array <tt>[lat,lon]</tt>.
146
+ # Fetch coordinates and assign +latitude+ and +longitude+. Also returns
147
+ # coordinates as an array: <tt>[lat, lon]</tt>.
146
148
  #
147
- def fetch_coordinates
149
+ def fetch_coordinates(save = false)
148
150
  location = send(self.class.geocoder_options[:method_name])
149
- Geocoder.fetch_coordinates(location)
151
+ returning Geocoder.fetch_coordinates(location) do |c|
152
+ unless c.blank?
153
+ method = (save ? "update" : "write") + "_attribute"
154
+ send method, self.class.geocoder_options[:latitude], c[0]
155
+ send method, self.class.geocoder_options[:longitude], c[1]
156
+ end
157
+ end
150
158
  end
151
-
159
+
152
160
  ##
153
- # Fetch coordinates and assign +latitude+ and +longitude+.
161
+ # Fetch coordinates and update (save) +latitude+ and +longitude+ data.
154
162
  #
155
163
  def fetch_coordinates!
156
- returning fetch_coordinates do |c|
157
- unless c.blank?
158
- write_attribute(self.class.geocoder_options[:latitude], c[0])
159
- write_attribute(self.class.geocoder_options[:longitude], c[1])
160
- end
161
- end
164
+ fetch_coordinates(true)
162
165
  end
163
166
 
164
167
  ##
@@ -184,7 +187,7 @@ module Geocoder
184
187
  # Calculate the distance between two points on Earth (Haversine formula).
185
188
  # Takes two sets of coordinates and an options hash:
186
189
  #
187
- # +units+ :: <tt>:mi</tt> for miles (default), <tt>:km</tt> for kilometers
190
+ # <tt>:units</tt> :: <tt>:mi</tt> (default) or <tt>:km</tt>
188
191
  #
189
192
  def self.distance_between(lat1, lon1, lat2, lon2, options = {})
190
193
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rails-geocoder}
8
- s.version = "0.8.5"
8
+ s.version = "0.8.6"
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-10-26}
12
+ s.date = %q{2009-10-27}
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 = [
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
27
27
  "init.rb",
28
28
  "lib/geocoder.rb",
29
29
  "rails-geocoder.gemspec",
30
+ "tasks/geocoder_tasks.rake",
30
31
  "test/fixtures/madison_square_garden.xml",
31
32
  "test/geocoder_test.rb",
32
33
  "test/test_helper.rb"
@@ -0,0 +1,15 @@
1
+ def klass
2
+ class_name = ENV['CLASS'] || ENV['class']
3
+ raise "Please specify a CLASS (model)" unless class_name
4
+ Object.const_get(class_name)
5
+ end
6
+
7
+ namespace :geocode do
8
+
9
+ desc "Geocode all objects without coordinates."
10
+ task :all => :environment do
11
+ klass.not_geocoded.each do |obj|
12
+ obj.fetch_coordinates!
13
+ end
14
+ end
15
+ end
@@ -5,11 +5,6 @@ class GeocoderTest < Test::Unit::TestCase
5
5
  def test_fetch_coordinates
6
6
  v = Venue.new(*venue_params(:msg))
7
7
  assert_equal [40.7495760, -73.9916733], v.fetch_coordinates
8
- end
9
-
10
- def test_fetch_coordinates!
11
- v = Venue.new(*venue_params(:msg))
12
- v.fetch_coordinates!
13
8
  assert_equal [40.7495760, -73.9916733], [v.latitude, v.longitude]
14
9
  end
15
10
  end
data/test/test_helper.rb CHANGED
@@ -24,6 +24,10 @@ module ActiveRecord
24
24
  @attributes[attr_name] = value
25
25
  end
26
26
 
27
+ def update_attribute(attr_name, value)
28
+ write_attribute(attr_name, value)
29
+ end
30
+
27
31
  def self.named_scope(*args); end
28
32
  end
29
33
  end
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.5
4
+ version: 0.8.6
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-10-26 00:00:00 -04:00
12
+ date: 2009-10-27 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -33,6 +33,7 @@ files:
33
33
  - init.rb
34
34
  - lib/geocoder.rb
35
35
  - rails-geocoder.gemspec
36
+ - tasks/geocoder_tasks.rake
36
37
  - test/fixtures/madison_square_garden.xml
37
38
  - test/geocoder_test.rb
38
39
  - test/test_helper.rb