3 require File.join(File.dirname(__FILE__), 'test_helper')
5 GeoKit::Geocoders::provider_order=[:google,:us]
8 class Company < ActiveRecord::Base #:nodoc: all
12 # Configures everything.
13 class Location < ActiveRecord::Base #:nodoc: all
19 class Store < ActiveRecord::Base
20 acts_as_mappable :auto_geocode=>true
23 # Uses deviations from conventions.
24 class CustomLocation < ActiveRecord::Base #:nodoc: all
26 acts_as_mappable :distance_column_name => 'dist',
27 :default_units => :kms,
28 :default_formula => :flat,
29 :lat_column_name => 'latitude',
30 :lng_column_name => 'longitude'
33 "lat: #{latitude} lng: #{longitude} dist: #{dist}"
37 class ActsAsMappableTest < Test::Unit::TestCase #:nodoc: all
39 LOCATION_A_IP = "217.10.83.5"
41 #self.fixture_path = File.dirname(__FILE__) + '/fixtures'
42 #self.fixture_path = RAILS_ROOT + '/test/fixtures/'
43 #puts "Rails Path #{RAILS_ROOT}"
44 #puts "Fixture Path: #{self.fixture_path}"
45 #self.fixture_path = ' /Users/bill_eisenhauer/Projects/geokit_test/test/fixtures/'
46 fixtures :companies, :locations, :custom_locations, :stores
49 @location_a = GeoKit::GeoLoc.new
50 @location_a.lat = 32.918593
51 @location_a.lng = -96.958444
52 @location_a.city = "Irving"
53 @location_a.state = "TX"
54 @location_a.country_code = "US"
55 @location_a.success = true
57 @sw = GeoKit::LatLng.new(32.91663,-96.982841)
58 @ne = GeoKit::LatLng.new(32.96302,-96.919495)
59 @bounds_center=GeoKit::LatLng.new((@sw.lat+@ne.lat)/2,(@sw.lng+@ne.lng)/2)
61 @starbucks = companies(:starbucks)
62 @loc_a = locations(:a)
63 @custom_loc_a = custom_locations(:a)
64 @loc_e = locations(:e)
65 @custom_loc_e = custom_locations(:e)
68 def test_override_default_units_the_hard_way
69 Location.default_units = :kms
70 locations = Location.find(:all, :origin => @loc_a, :conditions => "distance < 3.97")
71 assert_equal 5, locations.size
72 locations = Location.count(:origin => @loc_a, :conditions => "distance < 3.97")
73 assert_equal 5, locations
74 Location.default_units = :miles
78 locations = Location.find(:all, :origin => @loc_a, :include => :company, :conditions => "company_id = 1")
79 assert !locations.empty?
80 assert_equal 1, locations[0].company.id
81 assert_equal 'Starbucks', locations[0].company.name
84 def test_distance_between_geocoded
85 GeoKit::Geocoders::MultiGeocoder.expects(:geocode).with("Irving, TX").returns(@location_a)
86 GeoKit::Geocoders::MultiGeocoder.expects(:geocode).with("San Francisco, CA").returns(@location_a)
87 assert_equal 0, Location.distance_between("Irving, TX", "San Francisco, CA")
90 def test_distance_to_geocoded
91 GeoKit::Geocoders::MultiGeocoder.expects(:geocode).with("Irving, TX").returns(@location_a)
92 assert_equal 0, @custom_loc_a.distance_to("Irving, TX")
95 def test_distance_to_geocoded_error
96 GeoKit::Geocoders::MultiGeocoder.expects(:geocode).with("Irving, TX").returns(GeoKit::GeoLoc.new)
97 assert_raise(GeoKit::Geocoders::GeocodeError) { @custom_loc_a.distance_to("Irving, TX") }
100 def test_custom_attributes_distance_calculations
101 assert_equal 0, @custom_loc_a.distance_to(@loc_a)
102 assert_equal 0, CustomLocation.distance_between(@custom_loc_a, @loc_a)
105 def test_distance_column_in_select
106 locations = Location.find(:all, :origin => @loc_a, :order => "distance ASC")
107 assert_equal 6, locations.size
108 assert_equal 0, @loc_a.distance_to(locations.first)
109 assert_in_delta 3.97, @loc_a.distance_to(locations.last, :units => :miles, :formula => :sphere), 0.01
112 def test_find_with_distance_condition
113 locations = Location.find(:all, :origin => @loc_a, :conditions => "distance < 3.97")
114 assert_equal 5, locations.size
115 locations = Location.count(:origin => @loc_a, :conditions => "distance < 3.97")
116 assert_equal 5, locations
119 def test_find_with_distance_condition_with_units_override
120 locations = Location.find(:all, :origin => @loc_a, :units => :kms, :conditions => "distance < 6.387")
121 assert_equal 5, locations.size
122 locations = Location.count(:origin => @loc_a, :units => :kms, :conditions => "distance < 6.387")
123 assert_equal 5, locations
126 def test_find_with_distance_condition_with_formula_override
127 locations = Location.find(:all, :origin => @loc_a, :formula => :flat, :conditions => "distance < 6.387")
128 assert_equal 6, locations.size
129 locations = Location.count(:origin => @loc_a, :formula => :flat, :conditions => "distance < 6.387")
130 assert_equal 6, locations
134 locations = Location.find_within(3.97, :origin => @loc_a)
135 assert_equal 5, locations.size
136 locations = Location.count_within(3.97, :origin => @loc_a)
137 assert_equal 5, locations
140 def test_find_within_with_token
141 locations = Location.find(:all, :within => 3.97, :origin => @loc_a)
142 assert_equal 5, locations.size
143 locations = Location.count(:within => 3.97, :origin => @loc_a)
144 assert_equal 5, locations
147 def test_find_within_with_coordinates
148 locations = Location.find_within(3.97, :origin =>[@loc_a.lat,@loc_a.lng])
149 assert_equal 5, locations.size
150 locations = Location.count_within(3.97, :origin =>[@loc_a.lat,@loc_a.lng])
151 assert_equal 5, locations
154 def test_find_with_compound_condition
155 locations = Location.find(:all, :origin => @loc_a, :conditions => "distance < 5 and city = 'Coppell'")
156 assert_equal 2, locations.size
157 locations = Location.count(:origin => @loc_a, :conditions => "distance < 5 and city = 'Coppell'")
158 assert_equal 2, locations
161 def test_find_with_secure_compound_condition
162 locations = Location.find(:all, :origin => @loc_a, :conditions => ["distance < ? and city = ?", 5, 'Coppell'])
163 assert_equal 2, locations.size
164 locations = Location.count(:origin => @loc_a, :conditions => ["distance < ? and city = ?", 5, 'Coppell'])
165 assert_equal 2, locations
169 locations = Location.find_beyond(3.95, :origin => @loc_a)
170 assert_equal 1, locations.size
171 locations = Location.count_beyond(3.95, :origin => @loc_a)
172 assert_equal 1, locations
175 def test_find_beyond_with_token
176 locations = Location.find(:all, :beyond => 3.95, :origin => @loc_a)
177 assert_equal 1, locations.size
178 locations = Location.count(:beyond => 3.95, :origin => @loc_a)
179 assert_equal 1, locations
182 def test_find_beyond_with_coordinates
183 locations = Location.find_beyond(3.95, :origin =>[@loc_a.lat, @loc_a.lng])
184 assert_equal 1, locations.size
185 locations = Location.count_beyond(3.95, :origin =>[@loc_a.lat, @loc_a.lng])
186 assert_equal 1, locations
189 def test_find_range_with_token
190 locations = Location.find(:all, :range => 0..10, :origin => @loc_a)
191 assert_equal 6, locations.size
192 locations = Location.count(:range => 0..10, :origin => @loc_a)
193 assert_equal 6, locations
196 def test_find_range_with_token_with_conditions
197 locations = Location.find(:all, :origin => @loc_a, :range => 0..10, :conditions => ["city = ?", 'Coppell'])
198 assert_equal 2, locations.size
199 locations = Location.count(:origin => @loc_a, :range => 0..10, :conditions => ["city = ?", 'Coppell'])
200 assert_equal 2, locations
203 def test_find_range_with_token_excluding_end
204 locations = Location.find(:all, :range => 0...10, :origin => @loc_a)
205 assert_equal 6, locations.size
206 locations = Location.count(:range => 0...10, :origin => @loc_a)
207 assert_equal 6, locations
210 def test_find_nearest
211 assert_equal @loc_a, Location.find_nearest(:origin => @loc_a)
214 def test_find_nearest_through_find
215 assert_equal @loc_a, Location.find(:nearest, :origin => @loc_a)
218 def test_find_nearest_with_coordinates
219 assert_equal @loc_a, Location.find_nearest(:origin =>[@loc_a.lat, @loc_a.lng])
222 def test_find_farthest
223 assert_equal @loc_e, Location.find_farthest(:origin => @loc_a)
226 def test_find_farthest_through_find
227 assert_equal @loc_e, Location.find(:farthest, :origin => @loc_a)
230 def test_find_farthest_with_coordinates
231 assert_equal @loc_e, Location.find_farthest(:origin =>[@loc_a.lat, @loc_a.lng])
234 def test_scoped_distance_column_in_select
235 locations = @starbucks.locations.find(:all, :origin => @loc_a, :order => "distance ASC")
236 assert_equal 5, locations.size
237 assert_equal 0, @loc_a.distance_to(locations.first)
238 assert_in_delta 3.97, @loc_a.distance_to(locations.last, :units => :miles, :formula => :sphere), 0.01
241 def test_scoped_find_with_distance_condition
242 locations = @starbucks.locations.find(:all, :origin => @loc_a, :conditions => "distance < 3.97")
243 assert_equal 4, locations.size
244 locations = @starbucks.locations.count(:origin => @loc_a, :conditions => "distance < 3.97")
245 assert_equal 4, locations
248 def test_scoped_find_within
249 locations = @starbucks.locations.find_within(3.97, :origin => @loc_a)
250 assert_equal 4, locations.size
251 locations = @starbucks.locations.count_within(3.97, :origin => @loc_a)
252 assert_equal 4, locations
255 def test_scoped_find_with_compound_condition
256 locations = @starbucks.locations.find(:all, :origin => @loc_a, :conditions => "distance < 5 and city = 'Coppell'")
257 assert_equal 2, locations.size
258 locations = @starbucks.locations.count( :origin => @loc_a, :conditions => "distance < 5 and city = 'Coppell'")
259 assert_equal 2, locations
262 def test_scoped_find_beyond
263 locations = @starbucks.locations.find_beyond(3.95, :origin => @loc_a)
264 assert_equal 1, locations.size
265 locations = @starbucks.locations.count_beyond(3.95, :origin => @loc_a)
266 assert_equal 1, locations
269 def test_scoped_find_nearest
270 assert_equal @loc_a, @starbucks.locations.find_nearest(:origin => @loc_a)
273 def test_scoped_find_farthest
274 assert_equal @loc_e, @starbucks.locations.find_farthest(:origin => @loc_a)
277 def test_ip_geocoded_distance_column_in_select
278 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
279 locations = Location.find(:all, :origin => LOCATION_A_IP, :order => "distance ASC")
280 assert_equal 6, locations.size
281 assert_equal 0, @loc_a.distance_to(locations.first)
282 assert_in_delta 3.97, @loc_a.distance_to(locations.last, :units => :miles, :formula => :sphere), 0.01
285 def test_ip_geocoded_find_with_distance_condition
286 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
287 locations = Location.find(:all, :origin => LOCATION_A_IP, :conditions => "distance < 3.97")
288 assert_equal 5, locations.size
289 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
290 locations = Location.count(:origin => LOCATION_A_IP, :conditions => "distance < 3.97")
291 assert_equal 5, locations
294 def test_ip_geocoded_find_within
295 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
296 locations = Location.find_within(3.97, :origin => LOCATION_A_IP)
297 assert_equal 5, locations.size
298 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
299 locations = Location.count_within(3.97, :origin => LOCATION_A_IP)
300 assert_equal 5, locations
303 def test_ip_geocoded_find_with_compound_condition
304 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
305 locations = Location.find(:all, :origin => LOCATION_A_IP, :conditions => "distance < 5 and city = 'Coppell'")
306 assert_equal 2, locations.size
307 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
308 locations = Location.count(:origin => LOCATION_A_IP, :conditions => "distance < 5 and city = 'Coppell'")
309 assert_equal 2, locations
312 def test_ip_geocoded_find_with_secure_compound_condition
313 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
314 locations = Location.find(:all, :origin => LOCATION_A_IP, :conditions => ["distance < ? and city = ?", 5, 'Coppell'])
315 assert_equal 2, locations.size
316 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
317 locations = Location.count(:origin => LOCATION_A_IP, :conditions => ["distance < ? and city = ?", 5, 'Coppell'])
318 assert_equal 2, locations
321 def test_ip_geocoded_find_beyond
322 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
323 locations = Location.find_beyond(3.95, :origin => LOCATION_A_IP)
324 assert_equal 1, locations.size
325 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
326 locations = Location.count_beyond(3.95, :origin => LOCATION_A_IP)
327 assert_equal 1, locations
330 def test_ip_geocoded_find_nearest
331 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
332 assert_equal @loc_a, Location.find_nearest(:origin => LOCATION_A_IP)
335 def test_ip_geocoded_find_farthest
336 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with(LOCATION_A_IP).returns(@location_a)
337 assert_equal @loc_e, Location.find_farthest(:origin => LOCATION_A_IP)
340 def test_ip_geocoder_exception
341 GeoKit::Geocoders::IpGeocoder.expects(:geocode).with('127.0.0.1').returns(GeoKit::GeoLoc.new)
342 assert_raises GeoKit::Geocoders::GeocodeError do
343 Location.find_farthest(:origin => '127.0.0.1')
347 def test_address_geocode
348 GeoKit::Geocoders::MultiGeocoder.expects(:geocode).with('Irving, TX').returns(@location_a)
349 locations = Location.find(:all, :origin => 'Irving, TX', :conditions => ["distance < ? and city = ?", 5, 'Coppell'])
350 assert_equal 2, locations.size
353 def test_find_with_custom_distance_condition
354 locations = CustomLocation.find(:all, :origin => @loc_a, :conditions => "dist < 3.97")
355 assert_equal 5, locations.size
356 locations = CustomLocation.count(:origin => @loc_a, :conditions => "dist < 3.97")
357 assert_equal 5, locations
360 def test_find_with_custom_distance_condition_using_custom_origin
361 locations = CustomLocation.find(:all, :origin => @custom_loc_a, :conditions => "dist < 3.97")
362 assert_equal 5, locations.size
363 locations = CustomLocation.count(:origin => @custom_loc_a, :conditions => "dist < 3.97")
364 assert_equal 5, locations
367 def test_find_within_with_custom
368 locations = CustomLocation.find_within(3.97, :origin => @loc_a)
369 assert_equal 5, locations.size
370 locations = CustomLocation.count_within(3.97, :origin => @loc_a)
371 assert_equal 5, locations
374 def test_find_within_with_coordinates_with_custom
375 locations = CustomLocation.find_within(3.97, :origin =>[@loc_a.lat, @loc_a.lng])
376 assert_equal 5, locations.size
377 locations = CustomLocation.count_within(3.97, :origin =>[@loc_a.lat, @loc_a.lng])
378 assert_equal 5, locations
381 def test_find_with_compound_condition_with_custom
382 locations = CustomLocation.find(:all, :origin => @loc_a, :conditions => "dist < 5 and city = 'Coppell'")
383 assert_equal 1, locations.size
384 locations = CustomLocation.count(:origin => @loc_a, :conditions => "dist < 5 and city = 'Coppell'")
385 assert_equal 1, locations
388 def test_find_with_secure_compound_condition_with_custom
389 locations = CustomLocation.find(:all, :origin => @loc_a, :conditions => ["dist < ? and city = ?", 5, 'Coppell'])
390 assert_equal 1, locations.size
391 locations = CustomLocation.count(:origin => @loc_a, :conditions => ["dist < ? and city = ?", 5, 'Coppell'])
392 assert_equal 1, locations
395 def test_find_beyond_with_custom
396 locations = CustomLocation.find_beyond(3.95, :origin => @loc_a)
397 assert_equal 1, locations.size
398 locations = CustomLocation.count_beyond(3.95, :origin => @loc_a)
399 assert_equal 1, locations
402 def test_find_beyond_with_coordinates_with_custom
403 locations = CustomLocation.find_beyond(3.95, :origin =>[@loc_a.lat, @loc_a.lng])
404 assert_equal 1, locations.size
405 locations = CustomLocation.count_beyond(3.95, :origin =>[@loc_a.lat, @loc_a.lng])
406 assert_equal 1, locations
409 def test_find_nearest_with_custom
410 assert_equal @custom_loc_a, CustomLocation.find_nearest(:origin => @loc_a)
413 def test_find_nearest_with_coordinates_with_custom
414 assert_equal @custom_loc_a, CustomLocation.find_nearest(:origin =>[@loc_a.lat, @loc_a.lng])
417 def test_find_farthest_with_custom
418 assert_equal @custom_loc_e, CustomLocation.find_farthest(:origin => @loc_a)
421 def test_find_farthest_with_coordinates_with_custom
422 assert_equal @custom_loc_e, CustomLocation.find_farthest(:origin =>[@loc_a.lat, @loc_a.lng])
425 def test_find_with_array_origin
426 locations = Location.find(:all, :origin =>[@loc_a.lat,@loc_a.lng], :conditions => "distance < 3.97")
427 assert_equal 5, locations.size
428 locations = Location.count(:origin =>[@loc_a.lat,@loc_a.lng], :conditions => "distance < 3.97")
429 assert_equal 5, locations
435 def test_find_within_bounds
436 locations = Location.find_within_bounds([@sw,@ne])
437 assert_equal 2, locations.size
438 locations = Location.count_within_bounds([@sw,@ne])
439 assert_equal 2, locations
442 def test_find_within_bounds_ordered_by_distance
443 locations = Location.find_within_bounds([@sw,@ne], :origin=>@bounds_center, :order=>'distance asc')
444 assert_equal locations[0], locations(:d)
445 assert_equal locations[1], locations(:a)
448 def test_find_within_bounds_with_token
449 locations = Location.find(:all, :bounds=>[@sw,@ne])
450 assert_equal 2, locations.size
451 locations = Location.count(:bounds=>[@sw,@ne])
452 assert_equal 2, locations
455 def test_find_within_bounds_with_string_conditions
456 locations = Location.find(:all, :bounds=>[@sw,@ne], :conditions=>"id !=#{locations(:a).id}")
457 assert_equal 1, locations.size
460 def test_find_within_bounds_with_array_conditions
461 locations = Location.find(:all, :bounds=>[@sw,@ne], :conditions=>["id != ?", locations(:a).id])
462 assert_equal 1, locations.size
465 def test_auto_geocode
466 GeoKit::Geocoders::MultiGeocoder.expects(:geocode).with("Irving, TX").returns(@location_a)
467 store=Store.new(:address=>'Irving, TX')
469 assert_equal store.lat,@location_a.lat
470 assert_equal store.lng,@location_a.lng
471 assert_equal 0, store.errors.size
474 def test_auto_geocode_failure
475 GeoKit::Geocoders::MultiGeocoder.expects(:geocode).with("BOGUS").returns(GeoKit::GeoLoc.new)
476 store=Store.new(:address=>'BOGUS')
478 assert store.new_record?
479 assert_equal 1, store.errors.size