rails-geocoder 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  Per-release changes to Geocoder.
4
4
 
5
+ == 0.9.5 (2010 Oct 15)
6
+
7
+ * Fix broken PostgreSQL compatibility (now 100% compatible).
8
+ * Switch from Google's XML to JSON geocoding API.
9
+ * Separate Rails 2 and Rails 3-compatible branches.
10
+ * Don't allow :conditions hash in 'options' argument to 'nearbys' method (was deprecated in 0.9.3).
11
+
5
12
  == 0.9.4 (2010 Aug 2)
6
13
 
7
14
  * Google Maps API key no longer required (uses geocoder v3).
data/README.rdoc CHANGED
@@ -2,46 +2,33 @@
2
2
 
3
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 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.
4
4
 
5
- <b>Geocoder is currently compatible with Rails 2.x and Rails 3.</b> Also, a Google Maps API key is no longer necessary.
5
+ Geocoder is compatible with Rails 2.x and 3.x. <b>This is the README for the 3.x branch.</b> Please see the 2.x branch for installation instructions, documentation, and issues.
6
6
 
7
7
 
8
8
  == 1. Install
9
9
 
10
- === a. Rails 2
10
+ === As a Gem
11
11
 
12
- Install either as a plugin:
12
+ Add this to your Gemfile:
13
13
 
14
- script/plugin install git://github.com/alexreisner/geocoder.git
15
-
16
- or as a gem:
14
+ gem "rails-geocoder", :require => "geocoder"
17
15
 
18
- # add to config/environment.rb:
19
- config.gem "rails-geocoder", :lib => "geocoder", :source => "http://gemcutter.org/"
20
-
21
- # at command prompt:
22
- sudo rake gems:install
16
+ and run this at the command prompt:
23
17
 
18
+ bundle install
24
19
 
25
- === b. Rails 3
20
+ === Or As a Plugin
26
21
 
27
- Install either as a plugin:
22
+ At the command prompt:
28
23
 
29
24
  rails plugin install git://github.com/alexreisner/geocoder.git
30
25
 
31
- or as a gem:
32
-
33
- # add to Gemfile:
34
- gem "rails-geocoder", :require => "geocoder"
35
-
36
- # at command prompt:
37
- bundle install
38
-
39
26
 
40
27
  == 2. Configure
41
28
 
42
29
  A) Add +latitude+ and +longitude+ columns to your model:
43
30
 
44
- script/generate migration AddLatitudeAndLongitudeToYourModel latitude:float longitude:float
31
+ rails generate migration AddLatitudeAndLongitudeToYourModel latitude:float longitude:float
45
32
  rake db:migrate
46
33
 
47
34
  B) Tell geocoder where your model stores its address:
@@ -82,10 +69,10 @@ Some utility methods are also available:
82
69
 
83
70
  # distance (in miles) between Eiffel Tower and Empire State Building
84
71
  Geocoder.distance_between( 48.858205,2.294359, 40.748433,-73.985655 )
85
-
72
+
86
73
  # look up coordinates of some location (like searching Google Maps)
87
74
  Geocoder.fetch_coordinates("25 Main St, Cooperstown, NY")
88
-
75
+
89
76
  # find the geographic center (aka center of gravity) of objects or points
90
77
  Geocoder.geographic_center([ city1, city2, city3, [40.22,-73.99], city4 ])
91
78
 
@@ -144,9 +131,16 @@ If anyone has a more elegant solution to this problem I am very interested in se
144
131
 
145
132
  == To-do List
146
133
 
147
- * make 'near' scope work with 'select' options
134
+ * use completely separate "drivers" for different AR adapters?
135
+ * seems reasonable since we're using very DB-specific features
136
+ * also need to make sure 'mysql2' is supported
137
+ * add reverse geocoding
138
+ * make 'near' scope work with AR associations
139
+ * http://stackoverflow.com/questions/3266358/geocoder-rails-plugin-near-search-problem-with-activerecord
148
140
  * prepend table names to column names in SQL distance expression (required
149
141
  to do joins on another geocoded model)
142
+ * unobtrusively add ability to get a result with more data (Geocoder object?)
143
+ * the default usage should remain dead simple
150
144
 
151
145
 
152
146
  Copyright (c) 2009-10 Alex Reisner, released under the MIT license
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.4
1
+ 0.9.5
data/lib/geocoder.rb CHANGED
@@ -1,10 +1,8 @@
1
- require 'rexml/document'
2
-
3
1
  ##
4
2
  # Add geocoding functionality (via Google) to any object.
5
3
  #
6
4
  module Geocoder
7
-
5
+
8
6
  ##
9
7
  # Implementation of 'included' hook method.
10
8
  #
@@ -13,21 +11,21 @@ module Geocoder
13
11
  base.class_eval do
14
12
 
15
13
  # scope: geocoded objects
16
- send(Geocoder.scope_method_name, :geocoded,
14
+ scope :geocoded,
17
15
  :conditions => "#{geocoder_options[:latitude]} IS NOT NULL " +
18
- "AND #{geocoder_options[:longitude]} IS NOT NULL")
16
+ "AND #{geocoder_options[:longitude]} IS NOT NULL"
19
17
 
20
18
  # scope: not-geocoded objects
21
- send(Geocoder.scope_method_name, :not_geocoded,
19
+ scope :not_geocoded,
22
20
  :conditions => "#{geocoder_options[:latitude]} IS NULL " +
23
- "OR #{geocoder_options[:longitude]} IS NULL")
24
-
21
+ "OR #{geocoder_options[:longitude]} IS NULL"
22
+
25
23
  ##
26
24
  # Find all objects within a radius (in miles) of the given location
27
25
  # (address string). Location (the first argument) may be either a string
28
26
  # to geocode or an array of coordinates (<tt>[lat,long]</tt>).
29
27
  #
30
- send(Geocoder.scope_method_name, :near, lambda{ |location, *args|
28
+ scope :near, lambda{ |location, *args|
31
29
  latitude, longitude = location.is_a?(Array) ?
32
30
  location : Geocoder.fetch_coordinates(location)
33
31
  if latitude and longitude
@@ -35,10 +33,10 @@ module Geocoder
35
33
  else
36
34
  {}
37
35
  end
38
- })
36
+ }
39
37
  end
40
38
  end
41
-
39
+
42
40
  ##
43
41
  # Methods which will be class methods of the including class.
44
42
  #
@@ -48,13 +46,16 @@ module Geocoder
48
46
  # Get options hash suitable for passing to ActiveRecord.find to get
49
47
  # records within a radius (in miles) of the given point.
50
48
  # Options hash may include:
51
- #
52
- # +order+ :: column(s) for ORDER BY SQL clause
53
- # +limit+ :: number of records to return (for LIMIT SQL clause)
54
- # +offset+ :: number of records to skip (for OFFSET SQL clause)
55
- # +select+ :: string with the SELECT SQL fragment (e.g. “id, name”)
49
+ #
50
+ # +units+ :: <tt>:mi</tt> (default) or <tt>:km</tt>
51
+ # +exclude+ :: an object to exclude (used by the #nearbys method)
52
+ # +order+ :: column(s) for ORDER BY SQL clause
53
+ # +limit+ :: number of records to return (for LIMIT SQL clause)
54
+ # +offset+ :: number of records to skip (for OFFSET SQL clause)
55
+ # +select+ :: string with the SELECT SQL fragment (e.g. “id, name”)
56
56
  #
57
57
  def near_scope_options(latitude, longitude, radius = 20, options = {})
58
+ radius *= km_in_mi if options[:units] == :km
58
59
  if ActiveRecord::Base.connection.adapter_name == "SQLite"
59
60
  approx_near_scope_options(latitude, longitude, radius, options)
60
61
  else
@@ -68,7 +69,7 @@ module Geocoder
68
69
  ##
69
70
  # Scope options hash for use with a database that supports POWER(),
70
71
  # SQRT(), PI(), and trigonometric functions (SIN(), COS(), and ASIN()).
71
- #
72
+ #
72
73
  # Taken from the excellent tutorial at:
73
74
  # http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL
74
75
  #
@@ -99,7 +100,7 @@ module Geocoder
99
100
  :select => options[:select] || nil
100
101
  )
101
102
  end
102
-
103
+
103
104
  ##
104
105
  # Options used for any near-like scope.
105
106
  #
@@ -109,27 +110,19 @@ module Geocoder
109
110
  conditions = \
110
111
  ["#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] +
111
112
  coordinate_bounds(latitude, longitude, radius)
112
-
113
- # Handle conditions. Passing of conditions by developers is deprecated
114
- # but we will still need to handle conditions so, for example, we can
115
- # exclude objects by ID from the nearbys method. This is incredibly
116
- # ugly and doesn't work for a conditions hash: try using Arel?
117
- if options[:conditions].is_a?(String)
118
- options[:conditions] = [options[:conditions]]
119
- end
120
- if options[:conditions].is_a?(Array)
121
- conditions[0] = "(#{conditions[0]}) AND #{options[:conditions][0]}"
122
- conditions << options[:conditions][1]
113
+ if obj = options[:exclude]
114
+ conditions[0] << " AND id != ?"
115
+ conditions << obj.id
123
116
  end
124
-
125
117
  {
118
+ :group => columns.map{ |c| c.name}.join(','),
126
119
  :order => options[:order],
127
120
  :limit => options[:limit],
128
121
  :offset => options[:offset],
129
122
  :conditions => conditions
130
123
  }
131
124
  end
132
-
125
+
133
126
  ##
134
127
  # Get the rough high/low lat/long bounds for a geographic point and
135
128
  # radius. Returns an array: <tt>[lat_lo, lat_hi, lon_lo, lon_hi]</tt>.
@@ -145,6 +138,13 @@ module Geocoder
145
138
  longitude + (radius / factor)
146
139
  ]
147
140
  end
141
+
142
+ ##
143
+ # Conversion factor: km to mi.
144
+ #
145
+ def km_in_mi
146
+ 0.621371192
147
+ end
148
148
  end
149
149
 
150
150
  ##
@@ -161,7 +161,7 @@ module Geocoder
161
161
  def geocoded?
162
162
  read_coordinates.compact.size > 0
163
163
  end
164
-
164
+
165
165
  ##
166
166
  # Calculate the distance from the object to a point (lat,lon).
167
167
  # Valid units are defined in <tt>distance_between</tt> class method.
@@ -171,26 +171,17 @@ module Geocoder
171
171
  mylat,mylon = read_coordinates
172
172
  Geocoder.distance_between(mylat, mylon, lat, lon, :units => units)
173
173
  end
174
-
174
+
175
175
  ##
176
- # Get other geocoded objects within a given radius (in miles). Takes a
177
- # radius (in miles) and options for passing to the +near+ scope
178
- # (<tt>:order</tt>, <tt>:limit</tt>, and <tt>:offset</tt>).
176
+ # Get other geocoded objects within a given radius.
177
+ # Valid units are defined in <tt>distance_between</tt> class method.
179
178
  #
180
- def nearbys(radius = 20, options = {})
181
- if options != {}
182
- warn "DEPRECATION WARNING: The 'options' argument to the nearbys " +
183
- "method is deprecated and will be removed from rails-geocoder in " +
184
- "a future version. Nearbys now returns a scope so you should " +
185
- "specify more scopes and/or conditions via chaining. For example: " +
186
- "city.nearbys(20).order('name').limit(10). Support for Rails 2.x " +
187
- "will be discontinued soon."
188
- end
179
+ def nearbys(radius = 20, units = :mi)
189
180
  return [] unless geocoded?
190
- options.reverse_merge!(:conditions => ["id != ?", id])
181
+ options = {:exclude => self, :units => units}
191
182
  self.class.near(read_coordinates, radius, options)
192
183
  end
193
-
184
+
194
185
  ##
195
186
  # Fetch coordinates and assign +latitude+ and +longitude+. Also returns
196
187
  # coordinates as an array: <tt>[lat, lon]</tt>.
@@ -214,55 +205,36 @@ module Geocoder
214
205
  fetch_coordinates(true)
215
206
  end
216
207
 
217
- ##
218
- # Query Google for the coordinates of the given phrase.
219
- # Returns array [lat,lon] if found, nil if not found or if network error.
220
- #
221
- def self.fetch_coordinates(query)
222
- return nil if query.blank?
223
- return nil unless doc = self.search(query)
224
-
225
- # make sure search found a result
226
- e = doc.elements['GeocodeResponse/status']
227
- return nil unless (e and e.text == "OK")
228
-
229
- # isolate the relevant part of the result
230
- place = doc.elements['GeocodeResponse/result/geometry/location']
231
-
232
- # blindly use the first results (assume they are most accurate)
233
- ['lat', 'lng'].map{ |i| place.elements[i].text.to_f }
234
- end
235
-
236
208
  ##
237
209
  # Calculate the distance between two points on Earth (Haversine formula).
238
210
  # Takes two sets of coordinates and an options hash:
239
- #
211
+ #
240
212
  # <tt>:units</tt> :: <tt>:mi</tt> (default) or <tt>:km</tt>
241
213
  #
242
214
  def self.distance_between(lat1, lon1, lat2, lon2, options = {})
243
-
215
+
244
216
  # set default options
245
217
  options[:units] ||= :mi
246
-
218
+
247
219
  # define conversion factors
248
- units = { :mi => 3956, :km => 6371 }
249
-
220
+ conversions = { :mi => 3956, :km => 6371 }
221
+
250
222
  # convert degrees to radians
251
223
  lat1 = to_radians(lat1)
252
224
  lon1 = to_radians(lon1)
253
225
  lat2 = to_radians(lat2)
254
226
  lon2 = to_radians(lon2)
255
-
227
+
256
228
  # compute distances
257
229
  dlat = (lat1 - lat2).abs
258
230
  dlon = (lon1 - lon2).abs
259
-
231
+
260
232
  a = (Math.sin(dlat / 2))**2 + Math.cos(lat1) *
261
- (Math.sin(dlon / 2))**2 * Math.cos(lat2)
262
- c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a))
263
- c * units[options[:units]]
233
+ (Math.sin(dlon / 2))**2 * Math.cos(lat2)
234
+ c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a))
235
+ c * conversions[options[:units]]
264
236
  end
265
-
237
+
266
238
  ##
267
239
  # Compute the geographic center (aka geographic midpoint, center of
268
240
  # gravity) for an array of geocoded objects and/or [lat,lon] arrays
@@ -270,15 +242,15 @@ module Geocoder
270
242
  # the procedure documented at http://www.geomidpoint.com/calculation.html.
271
243
  #
272
244
  def self.geographic_center(points)
273
-
245
+
274
246
  # convert objects to [lat,lon] arrays and remove nils
275
247
  points = points.map{ |p|
276
248
  p.is_a?(Array) ? p : (p.geocoded?? p.read_coordinates : nil)
277
249
  }.compact
278
-
250
+
279
251
  # convert degrees to radians
280
252
  points.map!{ |p| [to_radians(p[0]), to_radians(p[1])] }
281
-
253
+
282
254
  # convert to Cartesian coordinates
283
255
  x = []; y = []; z = []
284
256
  points.each do |p|
@@ -291,12 +263,12 @@ module Geocoder
291
263
  xa, ya, za = [x,y,z].map do |c|
292
264
  c.inject(0){ |tot,i| tot += i } / c.size.to_f
293
265
  end
294
-
266
+
295
267
  # convert back to latitude/longitude
296
268
  lon = Math.atan2(ya, xa)
297
269
  hyp = Math.sqrt(xa**2 + ya**2)
298
270
  lat = Math.atan2(za, hyp)
299
-
271
+
300
272
  # return answer in degrees
301
273
  [to_degrees(lat), to_degrees(lon)]
302
274
  end
@@ -307,35 +279,57 @@ module Geocoder
307
279
  def self.to_radians(degrees)
308
280
  degrees * (Math::PI / 180)
309
281
  end
310
-
282
+
311
283
  ##
312
284
  # Convert radians to degrees.
313
285
  #
314
286
  def self.to_degrees(radians)
315
287
  (radians * 180.0) / Math::PI
316
288
  end
317
-
289
+
318
290
  ##
319
291
  # Query Google for geographic information about the given phrase.
292
+ # Returns a hash representing a valid geocoder response.
293
+ # Returns nil if non-200 HTTP response, timeout, or other error.
320
294
  #
321
295
  def self.search(query)
322
- if doc = _fetch_xml(query)
323
- REXML::Document.new(doc)
296
+ doc = _fetch_parsed_response(query)
297
+ doc && doc['status'] == "OK" ? doc : nil
298
+ end
299
+
300
+ ##
301
+ # Query Google for the coordinates of the given phrase.
302
+ # Returns array [lat,lon] if found, nil if not found or if network error.
303
+ #
304
+ def self.fetch_coordinates(query)
305
+ return nil unless doc = self.search(query)
306
+ # blindly use the first results (assume they are most accurate)
307
+ place = doc['results'].first['geometry']['location']
308
+ ['lat', 'lng'].map{ |i| place[i] }
309
+ end
310
+
311
+ ##
312
+ # Returns a parsed Google geocoder search result (hash).
313
+ # This method is not intended for general use (prefer Geocoder.search).
314
+ #
315
+ def self._fetch_parsed_response(query)
316
+ if doc = _fetch_raw_response(query)
317
+ ActiveSupport::JSON.decode(doc)
324
318
  end
325
319
  end
326
-
320
+
327
321
  ##
328
- # Request an XML geo search result from Google.
322
+ # Returns a raw Google geocoder search result (JSON).
329
323
  # This method is not intended for general use (prefer Geocoder.search).
330
324
  #
331
- def self._fetch_xml(query)
332
- params = {
333
- :address => query,
334
- :sensor => "false"
335
- }
336
- url = "http://maps.google.com/maps/api/geocode/xml?" + params.to_query
337
-
338
- # Query geocoder and make sure it responds quickly.
325
+ def self._fetch_raw_response(query)
326
+ return nil if query.blank?
327
+
328
+ # build URL
329
+ params = { :address => query, :sensor => "false" }
330
+ url = "http://maps.google.com/maps/api/geocode/json?" + params.to_query
331
+
332
+ # query geocoder and make sure it responds quickly
339
333
  begin
340
334
  resp = nil
341
335
  timeout(3) do
@@ -345,24 +339,13 @@ module Geocoder
345
339
  return nil
346
340
  end
347
341
  end
348
-
349
- ##
350
- # Name of the ActiveRecord scope method.
351
- #
352
- def self.scope_method_name
353
- begin
354
- Rails.version.starts_with?("3") ? :scope : :named_scope
355
- rescue NameError
356
- :named_scope
357
- end
358
- end
359
342
  end
360
343
 
361
344
  ##
362
345
  # Add geocoded_by method to ActiveRecord::Base so Geocoder is accessible.
363
346
  #
364
347
  ActiveRecord::Base.class_eval do
365
-
348
+
366
349
  ##
367
350
  # Set attribute names and include the Geocoder module.
368
351
  #
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rails-geocoder}
8
- s.version = "0.9.4"
8
+ s.version = "0.9.5"
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{2010-08-02}
12
+ s.date = %q{2010-10-15}
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 = [
@@ -28,25 +28,25 @@ Gem::Specification.new do |s|
28
28
  "lib/geocoder.rb",
29
29
  "lib/tasks/geocoder_tasks.rake",
30
30
  "rails-geocoder.gemspec",
31
- "test/fixtures/madison_square_garden.xml",
31
+ "test/fixtures/madison_square_garden.json",
32
32
  "test/geocoder_test.rb",
33
33
  "test/test_helper.rb"
34
34
  ]
35
35
  s.homepage = %q{http://github.com/alexreisner/geocoder}
36
36
  s.rdoc_options = ["--charset=UTF-8"]
37
37
  s.require_paths = ["lib"]
38
- s.rubygems_version = %q{1.3.6}
38
+ s.rubygems_version = %q{1.3.7}
39
39
  s.summary = %q{Add geocoding functionality to Rails models.}
40
40
  s.test_files = [
41
- "test/geocoder_test.rb",
42
- "test/test_helper.rb"
41
+ "test/test_helper.rb",
42
+ "test/geocoder_test.rb"
43
43
  ]
44
44
 
45
45
  if s.respond_to? :specification_version then
46
46
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
47
47
  s.specification_version = 3
48
48
 
49
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
50
  else
51
51
  end
52
52
  else
@@ -0,0 +1,57 @@
1
+ {
2
+ "status": "OK",
3
+ "results": [ {
4
+ "types": [ "street_address" ],
5
+ "formatted_address": "4 Penn Plaza, New York, NY 10001, USA",
6
+ "address_components": [ {
7
+ "long_name": "4",
8
+ "short_name": "4",
9
+ "types": [ "street_number" ]
10
+ }, {
11
+ "long_name": "Penn Plaza",
12
+ "short_name": "Penn Plaza",
13
+ "types": [ "route" ]
14
+ }, {
15
+ "long_name": "Manhattan",
16
+ "short_name": "Manhattan",
17
+ "types": [ "sublocality", "political" ]
18
+ }, {
19
+ "long_name": "New York",
20
+ "short_name": "New York",
21
+ "types": [ "locality", "political" ]
22
+ }, {
23
+ "long_name": "New York",
24
+ "short_name": "New York",
25
+ "types": [ "administrative_area_level_2", "political" ]
26
+ }, {
27
+ "long_name": "New York",
28
+ "short_name": "NY",
29
+ "types": [ "administrative_area_level_1", "political" ]
30
+ }, {
31
+ "long_name": "United States",
32
+ "short_name": "US",
33
+ "types": [ "country", "political" ]
34
+ }, {
35
+ "long_name": "10001",
36
+ "short_name": "10001",
37
+ "types": [ "postal_code" ]
38
+ } ],
39
+ "geometry": {
40
+ "location": {
41
+ "lat": 40.7503540,
42
+ "lng": -73.9933710
43
+ },
44
+ "location_type": "ROOFTOP",
45
+ "viewport": {
46
+ "southwest": {
47
+ "lat": 40.7473324,
48
+ "lng": -73.9965316
49
+ },
50
+ "northeast": {
51
+ "lat": 40.7536276,
52
+ "lng": -73.9902364
53
+ }
54
+ }
55
+ }
56
+ } ]
57
+ }
@@ -7,12 +7,12 @@ class GeocoderTest < Test::Unit::TestCase
7
7
  assert_equal [40.750354, -73.993371], v.fetch_coordinates
8
8
  assert_equal [40.750354, -73.993371], [v.latitude, v.longitude]
9
9
  end
10
-
10
+
11
11
  # sanity check
12
12
  def test_distance_between
13
13
  assert_equal 69, Geocoder.distance_between(0,0, 0,1).round
14
14
  end
15
-
15
+
16
16
  # sanity check
17
17
  def test_geographic_center
18
18
  assert_equal [0.0, 0.5],
data/test/test_helper.rb CHANGED
@@ -10,24 +10,24 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
10
10
  #
11
11
  module ActiveRecord
12
12
  class Base
13
-
13
+
14
14
  def initialize
15
15
  @attributes = {}
16
16
  end
17
-
17
+
18
18
  def read_attribute(attr_name)
19
19
  @attributes[attr_name.to_sym]
20
20
  end
21
-
21
+
22
22
  def write_attribute(attr_name, value)
23
23
  @attributes[attr_name.to_sym] = value
24
24
  end
25
-
25
+
26
26
  def update_attribute(attr_name, value)
27
27
  write_attribute(attr_name.to_sym, value)
28
28
  end
29
-
30
- def self.named_scope(*args); end
29
+
30
+ def self.scope(*args); end
31
31
  end
32
32
  end
33
33
 
@@ -38,9 +38,8 @@ require 'geocoder'
38
38
  # Mock HTTP request to Google.
39
39
  #
40
40
  module Geocoder
41
- def self._fetch_xml(query)
42
- filename = File.join("test", "fixtures", "madison_square_garden.xml")
43
- File.read(filename)
41
+ def self._fetch_raw_response(query)
42
+ File.read(File.join("test", "fixtures", "madison_square_garden.json"))
44
43
  end
45
44
  end
46
45
 
@@ -49,13 +48,13 @@ end
49
48
  #
50
49
  class Venue < ActiveRecord::Base
51
50
  geocoded_by :address
52
-
51
+
53
52
  def initialize(name, address)
54
53
  super()
55
54
  write_attribute :name, name
56
55
  write_attribute :address, address
57
56
  end
58
-
57
+
59
58
  ##
60
59
  # If method not found, assume it's an ActiveRecord attribute reader.
61
60
  #
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-geocoder
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 49
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 9
8
- - 4
9
- version: 0.9.4
9
+ - 5
10
+ version: 0.9.5
10
11
  platform: ruby
11
12
  authors:
12
13
  - Alex Reisner
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-08-02 00:00:00 -04:00
18
+ date: 2010-10-15 00:00:00 -04:00
18
19
  default_executable:
19
20
  dependencies: []
20
21
 
@@ -39,7 +40,7 @@ files:
39
40
  - lib/geocoder.rb
40
41
  - lib/tasks/geocoder_tasks.rake
41
42
  - rails-geocoder.gemspec
42
- - test/fixtures/madison_square_garden.xml
43
+ - test/fixtures/madison_square_garden.json
43
44
  - test/geocoder_test.rb
44
45
  - test/test_helper.rb
45
46
  has_rdoc: true
@@ -52,26 +53,30 @@ rdoc_options:
52
53
  require_paths:
53
54
  - lib
54
55
  required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
55
57
  requirements:
56
58
  - - ">="
57
59
  - !ruby/object:Gem::Version
60
+ hash: 3
58
61
  segments:
59
62
  - 0
60
63
  version: "0"
61
64
  required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
62
66
  requirements:
63
67
  - - ">="
64
68
  - !ruby/object:Gem::Version
69
+ hash: 3
65
70
  segments:
66
71
  - 0
67
72
  version: "0"
68
73
  requirements: []
69
74
 
70
75
  rubyforge_project:
71
- rubygems_version: 1.3.6
76
+ rubygems_version: 1.3.7
72
77
  signing_key:
73
78
  specification_version: 3
74
79
  summary: Add geocoding functionality to Rails models.
75
80
  test_files:
76
- - test/geocoder_test.rb
77
81
  - test/test_helper.rb
82
+ - test/geocoder_test.rb
@@ -1,69 +0,0 @@
1
- <GeocodeResponse>
2
- <status>OK</status>
3
- <result>
4
- <type>street_address</type>
5
- <formatted_address>4 Penn Plaza, New York, NY 10001, USA</formatted_address>
6
- <address_component>
7
- <long_name>4</long_name>
8
- <short_name>4</short_name>
9
- <type>street_number</type>
10
- </address_component>
11
- <address_component>
12
- <long_name>Penn Plaza</long_name>
13
- <short_name>Penn Plaza</short_name>
14
- <type>route</type>
15
- </address_component>
16
- <address_component>
17
- <long_name>Manhattan</long_name>
18
- <short_name>Manhattan</short_name>
19
- <type>sublocality</type>
20
- <type>political</type>
21
- </address_component>
22
- <address_component>
23
- <long_name>New York</long_name>
24
- <short_name>New York</short_name>
25
- <type>locality</type>
26
- <type>political</type>
27
- </address_component>
28
- <address_component>
29
- <long_name>New York</long_name>
30
- <short_name>New York</short_name>
31
- <type>administrative_area_level_2</type>
32
- <type>political</type>
33
- </address_component>
34
- <address_component>
35
- <long_name>New York</long_name>
36
- <short_name>NY</short_name>
37
- <type>administrative_area_level_1</type>
38
- <type>political</type>
39
- </address_component>
40
- <address_component>
41
- <long_name>United States</long_name>
42
- <short_name>US</short_name>
43
- <type>country</type>
44
- <type>political</type>
45
- </address_component>
46
- <address_component>
47
- <long_name>10001</long_name>
48
- <short_name>10001</short_name>
49
- <type>postal_code</type>
50
- </address_component>
51
- <geometry>
52
- <location>
53
- <lat>40.7503540</lat>
54
- <lng>-73.9933710</lng>
55
- </location>
56
- <location_type>ROOFTOP</location_type>
57
- <viewport>
58
- <southwest>
59
- <lat>40.7473324</lat>
60
- <lng>-73.9965316</lng>
61
- </southwest>
62
- <northeast>
63
- <lat>40.7536276</lat>
64
- <lng>-73.9902364</lng>
65
- </northeast>
66
- </viewport>
67
- </geometry>
68
- </result>
69
- </GeocodeResponse>