activerecord-spatial 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +16 -0
  3. data/Gemfile +21 -0
  4. data/Guardfile +17 -0
  5. data/MIT-LICENSE +23 -0
  6. data/README.rdoc +169 -0
  7. data/Rakefile +28 -0
  8. data/activerecord-spatial.gemspec +26 -0
  9. data/lib/activerecord-spatial.rb +32 -0
  10. data/lib/activerecord-spatial/active_record.rb +14 -0
  11. data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/adapter_extensions.rb +36 -0
  12. data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/postgis.rb +24 -0
  13. data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/unknown_srid.rb +21 -0
  14. data/lib/activerecord-spatial/active_record/models/geography_column.rb +17 -0
  15. data/lib/activerecord-spatial/active_record/models/geometry_column.rb +17 -0
  16. data/lib/activerecord-spatial/active_record/models/spatial_column.rb +22 -0
  17. data/lib/activerecord-spatial/active_record/models/spatial_ref_sys.rb +20 -0
  18. data/lib/activerecord-spatial/associations.rb +292 -0
  19. data/lib/activerecord-spatial/spatial_columns.rb +345 -0
  20. data/lib/activerecord-spatial/spatial_function.rb +201 -0
  21. data/lib/activerecord-spatial/spatial_scope_constants.rb +114 -0
  22. data/lib/activerecord-spatial/spatial_scopes.rb +297 -0
  23. data/lib/activerecord-spatial/version.rb +5 -0
  24. data/lib/tasks/test.rake +45 -0
  25. data/test/accessors_geographies_tests.rb +149 -0
  26. data/test/accessors_geometries_tests.rb +151 -0
  27. data/test/adapter_tests.rb +44 -0
  28. data/test/associations_tests.rb +656 -0
  29. data/test/database.yml +17 -0
  30. data/test/fixtures/bars.yml +16 -0
  31. data/test/fixtures/blorts.yml +37 -0
  32. data/test/fixtures/foo3ds.yml +17 -0
  33. data/test/fixtures/foo_geographies.yml +16 -0
  34. data/test/fixtures/foos.yml +16 -0
  35. data/test/fixtures/zortables.yml +36 -0
  36. data/test/geography_column_tests.rb +40 -0
  37. data/test/geometry_column_tests.rb +40 -0
  38. data/test/models/bar.rb +17 -0
  39. data/test/models/blort.rb +12 -0
  40. data/test/models/foo.rb +17 -0
  41. data/test/models/foo3d.rb +17 -0
  42. data/test/models/foo_geography.rb +16 -0
  43. data/test/models/zortable.rb +17 -0
  44. data/test/spatial_scopes_geographies_tests.rb +106 -0
  45. data/test/spatial_scopes_tests.rb +444 -0
  46. data/test/test_helper.rb +272 -0
  47. metadata +138 -0
@@ -0,0 +1,444 @@
1
+
2
+ $: << File.dirname(__FILE__)
3
+ require 'test_helper'
4
+
5
+ class SpatialScopesTests < ActiveRecordSpatialTestCase
6
+ def self.before_suite
7
+ load_models(:foo, :foo3d)
8
+ end
9
+
10
+ def ids_tester(method, args, ids = [], klass = Foo)
11
+ geoms = klass.send(method, *Array.wrap(args)).all
12
+ assert_equal(ids.sort, geoms.collect(&:id).sort)
13
+ end
14
+
15
+ def test_contains
16
+ ids_tester(:st_contains, 'POINT(3 3)', [ 3 ])
17
+ end
18
+
19
+ def test_containsproperly
20
+ ids_tester(:st_containsproperly, 'LINESTRING(-4 -4, 4 4)', [ 3 ])
21
+ end
22
+
23
+ def test_covers
24
+ ids_tester(:st_covers, 'LINESTRING(-4 -4, 4 4)', [ 3 ])
25
+ end
26
+
27
+ def test_coveredby
28
+ ids_tester(:st_coveredby, 'POLYGON((-6 -6, -6 6, 6 6, 6 -6, -6 -6))', [ 1, 3 ])
29
+ end
30
+
31
+ def test_crosses
32
+ ids_tester(:st_crosses, 'LINESTRING(-6 -6, 4 4)', [ 3 ])
33
+ end
34
+
35
+ def test_disjoint
36
+ ids_tester(:st_disjoint, 'POINT(100 100)', [ 1, 2, 3 ])
37
+ end
38
+
39
+ def test_equal
40
+ ids_tester(:st_equals, 'POLYGON((-5 -5, -5 5, 5 5, 5 -5, -5 -5))', [ 3 ])
41
+ end
42
+
43
+ def test_intersects
44
+ ids_tester(:st_intersects, 'LINESTRING(-5 -5, 10 10)', [ 1, 2, 3 ])
45
+ end
46
+
47
+ def test_orderingequals
48
+ ids_tester(:st_orderingequals, 'POLYGON((-5 -5, -5 5, 5 5, 5 -5, -5 -5))', [ 3 ])
49
+ end
50
+
51
+ def test_overlaps
52
+ ids_tester(:st_overlaps, 'POLYGON((-6 -6, -5 0, 0 0, 0 -5, -6 -6))', [ 3 ])
53
+ end
54
+
55
+ def test_touches
56
+ ids_tester(:st_touches, 'POLYGON((-5 -5, -5 -10, -10 -10, -10 -5, -5 -5))', [ 3 ])
57
+ end
58
+
59
+ def test_within
60
+ ids_tester(:st_within, 'POLYGON((-5 -5, 5 10, 20 20, 10 5, -5 -5))', [ 1, 2 ])
61
+ end
62
+
63
+ def test_dwithin
64
+ ids_tester(:st_dwithin, [ 'POINT(5 5)', 10 ], [ 1, 2, 3 ])
65
+ end
66
+
67
+ def test_dfullywithin
68
+ ids_tester(:st_dfullywithin, [ 'POINT(5 5)', 10 ], [ 1, 2 ])
69
+ end
70
+
71
+ def test_geometry_type
72
+ ids_tester(:st_geometry_type, 'ST_Point', [ 1, 2 ])
73
+ ids_tester(:st_geometry_type, [ 'ST_Point', 'ST_Polygon' ], [ 1, 2, 3 ])
74
+ ids_tester(:st_geometry_type, [ 'ST_MultiLineString' ], [])
75
+ end
76
+
77
+ def test_allow_null
78
+ begin
79
+ foo = Foo.create(:name => 'four')
80
+ ids_tester(:st_contains, [ 'POINT(3 3)', { :allow_null => true } ], [ 3, foo.id ])
81
+ ensure
82
+ Foo.find_by_name('four').destroy
83
+ end
84
+ end
85
+
86
+ def test_nil_relationship
87
+ assert_equal([ 1, 2, 3 ], Foo.st_within(nil).all.collect(&:id).sort)
88
+ end
89
+
90
+ def test_with_column
91
+ assert_equal([1, 2, 3], Foo.st_disjoint('POINT(100 100)', :column => :the_other_geom).all.collect(&:id).sort)
92
+ end
93
+
94
+ def test_with_srid_switching
95
+ assert_equal([1, 2, 3], Foo.st_disjoint('SRID=4326; POINT(100 100)').all.collect(&:id).sort)
96
+ end
97
+
98
+ def test_with_srid_default
99
+ assert_equal([1, 2, 3], Foo.st_disjoint('SRID=default; POINT(100 100)').all.collect(&:id).sort)
100
+ assert_equal([3], Foo.st_contains('SRID=default; POINT(-3 -3)').all.collect(&:id).sort)
101
+ end
102
+
103
+ def test_with_srid_transform
104
+ assert_equal([1, 2, 3], Foo.st_disjoint('SRID=4269; POINT(100 100)', :column => :the_other_geom).all.collect(&:id).sort)
105
+ assert_equal([3], Foo.st_contains('SRID=4269; POINT(7 7)', :column => :the_other_geom).all.collect(&:id).sort)
106
+ end
107
+
108
+ def test_order_by_st_distance
109
+ assert_equal([3, 1, 2], Foo.order_by_st_distance('POINT(1 1)').all.collect(&:id))
110
+ end
111
+
112
+ def test_order_by_st_distance_desc
113
+ assert_equal([2, 1, 3], Foo.order_by_st_distance('POINT(1 1)', :desc => true).all.collect(&:id))
114
+ end
115
+
116
+ def test_order_by_st_distance_sphere
117
+ assert_equal([3, 1, 2], Foo.order_by_st_distance_sphere('POINT(1 1)').all.collect(&:id))
118
+ end
119
+
120
+ def test_order_by_st_distance_sphere_desc
121
+ assert_equal([2, 1, 3], Foo.order_by_st_distance_sphere('POINT(1 1)', :desc => true).all.collect(&:id))
122
+ end
123
+
124
+ def test_order_by_st_max_distance
125
+ assert_equal([1, 3, 2], Foo.order_by_st_maxdistance('POINT(1 1)').all.collect(&:id))
126
+ end
127
+
128
+ def test_order_by_st_max_distance_desc
129
+ assert_equal([2, 3, 1], Foo.order_by_st_maxdistance('POINT(1 1)', :desc => true).all.collect(&:id))
130
+ end
131
+
132
+ def test_order_by_st_area
133
+ assert_equal([1, 2, 3], Foo.order_by_st_area.order('id').all.collect(&:id))
134
+ end
135
+
136
+ def test_order_by_st_area_desc
137
+ assert_equal([3, 1, 2], Foo.order_by_st_area(:desc => true).order('id').all.collect(&:id))
138
+ end
139
+
140
+ def test_order_by_st_ndims
141
+ assert_equal([1, 2, 3], Foo.order_by_st_ndims.order('id').all.collect(&:id))
142
+ end
143
+
144
+ def test_order_by_st_ndims_desc
145
+ assert_equal([1, 2, 3], Foo.order_by_st_ndims(:desc => true).order('id').all.collect(&:id))
146
+ end
147
+
148
+ def test_order_by_st_npoints
149
+ assert_equal([1, 2, 3], Foo.order_by_st_npoints.order('id').all.collect(&:id))
150
+ end
151
+
152
+ def test_order_by_st_npoints_desc
153
+ assert_equal([3, 1, 2], Foo.order_by_st_npoints(:desc => true).order('id').all.collect(&:id))
154
+ end
155
+
156
+ def test_order_by_st_nrings
157
+ assert_equal([1, 2, 3], Foo.order_by_st_nrings.order('id').all.collect(&:id))
158
+ end
159
+
160
+ def test_order_by_st_nrings_desc
161
+ assert_equal([3, 1, 2], Foo.order_by_st_nrings(:desc => true).order('id').all.collect(&:id))
162
+ end
163
+
164
+ def test_order_by_st_numgeometries
165
+ assert_equal([1, 2, 3], Foo.order_by_st_numgeometries.order('id').all.collect(&:id))
166
+ end
167
+
168
+ def test_order_by_st_numgeometries_desc
169
+ assert_equal([1, 2, 3], Foo.order_by_st_numgeometries(:desc => true).order('id').all.collect(&:id))
170
+ end
171
+
172
+ def test_order_by_st_numinteriorring
173
+ assert_equal([3, 1, 2], Foo.order_by_st_numinteriorring.order('id').all.collect(&:id))
174
+ end
175
+
176
+ def test_order_by_st_numinteriorring_desc
177
+ assert_equal([1, 2, 3], Foo.order_by_st_numinteriorring(:desc => true).order('id').all.collect(&:id))
178
+ end
179
+
180
+ def test_order_by_st_numinteriorrings
181
+ assert_equal([3, 1, 2], Foo.order_by_st_numinteriorrings.order('id').all.collect(&:id))
182
+ end
183
+
184
+ def test_order_by_st_numinteriorrings_desc
185
+ assert_equal([1, 2, 3], Foo.order_by_st_numinteriorrings(:desc => true).order('id').all.collect(&:id))
186
+ end
187
+
188
+ def test_order_by_st_numpoints
189
+ assert_equal([1, 2, 3], Foo.order_by_st_numpoints.order('id').all.collect(&:id))
190
+ end
191
+
192
+ def test_order_by_st_numpoints_desc
193
+ assert_equal([1, 2, 3], Foo.order_by_st_numpoints(:desc => true).order('id').all.collect(&:id))
194
+ end
195
+
196
+ def test_order_by_st_length3d
197
+ assert_equal([1, 2, 3], Foo.order_by_st_length3d.order('id').all.collect(&:id))
198
+ end
199
+
200
+ def test_order_by_st_length3d_desc
201
+ assert_equal([1, 2, 3], Foo.order_by_st_length3d(:desc => true).order('id').all.collect(&:id))
202
+ end
203
+
204
+ def test_order_by_st_length
205
+ assert_equal([1, 2, 3], Foo.order_by_st_length.order('id').all.collect(&:id))
206
+ end
207
+
208
+ def test_order_by_st_length_desc
209
+ assert_equal([1, 2, 3], Foo.order_by_st_length(:desc => true).order('id').all.collect(&:id))
210
+ end
211
+
212
+ def test_order_by_st_length2d
213
+ assert_equal([1, 2, 3], Foo.order_by_st_length2d.order('id').all.collect(&:id))
214
+ end
215
+
216
+ def test_order_by_st_length2d_desc
217
+ assert_equal([1, 2, 3], Foo.order_by_st_length2d(:desc => true).order('id').all.collect(&:id))
218
+ end
219
+
220
+ def test_order_by_st_length3d_spheroid
221
+ assert_equal([1, 2, 3], Foo.order_by_st_length3d_spheroid('SPHEROID["WGS 84", 6378137, 298.257223563]').order('id').all.collect(&:id))
222
+ end
223
+
224
+ def test_order_by_st_length3d_spheroid_desc
225
+ expected = if ActiveRecordSpatial::POSTGIS[:lib] >= '2.0'
226
+ [3, 1, 2]
227
+ else
228
+ [1, 2, 3]
229
+ end
230
+
231
+ assert_equal(expected, Foo.order_by_st_length3d_spheroid('SPHEROID["WGS 84", 6378137, 298.257223563]', :desc => true).order('id').all.collect(&:id))
232
+ end
233
+
234
+ def test_order_by_st_length2d_spheroid
235
+ assert_equal([1, 2, 3], Foo.order_by_st_length2d_spheroid('SPHEROID["WGS 84", 6378137, 298.257223563]').order('id').all.collect(&:id))
236
+ end
237
+
238
+ def test_order_by_st_length2d_spheroid_desc
239
+ assert_equal([3, 1, 2], Foo.order_by_st_length2d_spheroid('SPHEROID["WGS 84", 6378137, 298.257223563]', :desc => true).order('id').all.collect(&:id))
240
+ end
241
+
242
+ def test_order_by_st_length_spheroid
243
+ assert_equal([1, 2, 3], Foo.order_by_st_length_spheroid('SPHEROID["WGS 84", 6378137, 298.257223563]').order('id').all.collect(&:id))
244
+ end
245
+
246
+ def test_order_by_st_length_spheroid_desc
247
+ expected = if ActiveRecordSpatial::POSTGIS[:lib] >= '2.0'
248
+ [3, 1, 2]
249
+ else
250
+ [1, 2, 3]
251
+ end
252
+
253
+ assert_equal(expected, Foo.order_by_st_length_spheroid('SPHEROID["WGS 84", 6378137, 298.257223563]', :desc => true).order('id').all.collect(&:id))
254
+ end
255
+
256
+ def test_order_by_st_perimeter
257
+ assert_equal([1, 2, 3], Foo.order_by_st_perimeter.order('id').all.collect(&:id))
258
+ end
259
+
260
+ def test_order_by_st_perimeter_desc
261
+ assert_equal([3, 1, 2], Foo.order_by_st_perimeter(:desc => true).order('id').all.collect(&:id))
262
+ end
263
+
264
+ def test_order_by_st_perimeter2d
265
+ assert_equal([1, 2, 3], Foo.order_by_st_perimeter2d.order('id').all.collect(&:id))
266
+ end
267
+
268
+ def test_order_by_st_perimeter2d_desc
269
+ assert_equal([3, 1, 2], Foo.order_by_st_perimeter2d(:desc => true).order('id').all.collect(&:id))
270
+ end
271
+
272
+ def test_order_by_st_perimeter3d
273
+ assert_equal([1, 2, 3], Foo.order_by_st_perimeter3d.order('id').all.collect(&:id))
274
+ end
275
+
276
+ def test_order_by_st_perimeter3d_desc
277
+ assert_equal([3, 1, 2], Foo.order_by_st_perimeter3d(:desc => true).order('id').all.collect(&:id))
278
+ end
279
+
280
+ def test_order_by_st_hausdorffdistance
281
+ assert_equal([1, 3, 2], Foo.order_by_st_hausdorffdistance('POINT(1 1)').all.collect(&:id))
282
+ end
283
+
284
+ def test_order_by_st_hausdorffdistance_desc
285
+ assert_equal([2, 3, 1], Foo.order_by_st_hausdorffdistance('POINT(1 1)', :desc => true).all.collect(&:id))
286
+ end
287
+
288
+ def test_order_by_st_hausdorffdistance_with_densify_frac
289
+ assert_equal([1, 3, 2], Foo.order_by_st_hausdorffdistance('POINT(1 1)', 0.314).all.collect(&:id))
290
+ end
291
+
292
+ def test_order_by_st_distance_spheroid
293
+ assert_equal([2, 3, 1], Foo.order_by_st_distance_spheroid('POINT(10 10)', 'SPHEROID["WGS 84", 6378137, 298.257223563]').order('id').all.collect(&:id))
294
+ end
295
+
296
+ def test_order_by_st_distance_spheroid_desc
297
+ assert_equal([1, 3, 2], Foo.order_by_st_distance_spheroid('POINT(10 10)', 'SPHEROID["WGS 84", 6378137, 298.257223563]', :desc => true).order('id').all.collect(&:id))
298
+ end
299
+
300
+ def test_order_by_st_area_with_desc_symbol
301
+ assert_equal([3, 1, 2], Foo.order_by_st_area(:desc).order('id').all.collect(&:id))
302
+ end
303
+
304
+ def test_3dintersects
305
+ skip('ST_3dintersects is unavailable') unless Foo3d.respond_to?(:st_3dintersects)
306
+
307
+ ids_tester(:st_3dintersects, 'LINESTRING(-5 -5 -5, 10 10 10)', [ 1, 3 ], Foo3d)
308
+ end
309
+
310
+ def test_3ddistance
311
+ skip('ST_3ddistance is unavailable') unless Foo3d.respond_to?(:order_by_st_3ddistance)
312
+
313
+ assert_equal([3, 2, 1], Foo3d.order_by_st_3ddistance('POINT(10 10)').order('id').all.collect(&:id))
314
+ end
315
+
316
+ def test_3dmaxdistance
317
+ skip('ST_3dmaxdistance is unavailable') unless Foo3d.respond_to?(:order_by_st_3dmaxdistance)
318
+
319
+ assert_equal([2, 1, 3], Foo3d.order_by_st_3dmaxdistance('POINT(10 10)').order('id').all.collect(&:id))
320
+ end
321
+
322
+ def test_3ddwithin
323
+ skip('ST_3ddwithin is unavailable') unless Foo3d.respond_to?(:st_3ddwithin)
324
+
325
+ ids_tester(:st_3ddwithin, [ 'LINESTRING(-5 -5 -5, 10 10 10)', 10 ], [ 1, 2, 3 ], Foo3d)
326
+ end
327
+
328
+ def test_3ddfullywithin
329
+ skip('ST_3ddfullywithin is unavilable') unless Foo3d.respond_to?(:st_3ddfullywithin)
330
+
331
+ ids_tester(:st_3ddfullywithin, [ 'LINESTRING(-10 -10 -10, 10 10 10)', 100 ], [ 1, 2, 3 ], Foo3d)
332
+ end
333
+
334
+ def test_order_by_with_column_wrapper
335
+ values = nil
336
+
337
+ assert_sql(/ST_envelope\("foos"."the_geom"\)/) do
338
+ values = Foo.
339
+ order_by_st_perimeter(
340
+ :desc => true,
341
+ :column => {
342
+ :wrapper => :envelope
343
+ }
344
+ ).order('id').all.collect(&:id)
345
+ end
346
+
347
+ assert_equal([3, 1, 2], values)
348
+ end
349
+
350
+ def test_order_by_with_column_wrapper_and_an_option
351
+ values = nil
352
+
353
+ assert_sql(/ST_geometryn\("foos"."the_geom", 1\)/) do
354
+ values = Foo.
355
+ order_by_st_perimeter(
356
+ :desc => true,
357
+ :column => {
358
+ :wrapper => {
359
+ :geometryn => 1
360
+ }
361
+ }
362
+ ).order('id').all.collect(&:id)
363
+ end
364
+
365
+ assert_equal([3, 1, 2], values)
366
+ end
367
+
368
+ def test_order_by_with_column_wrapper_and_options
369
+ values = nil
370
+
371
+ assert_sql(/ST_snap\("foos"."the_geom", 'POINT \(0 0\)', 1.0\)/) do
372
+ values = Foo.
373
+ order_by_st_perimeter(
374
+ :desc => true,
375
+ :column => {
376
+ :wrapper => {
377
+ :snap => [
378
+ 'POINT (0 0)',
379
+ 1.0
380
+ ]
381
+ }
382
+ }
383
+ ).order('id').all.collect(&:id)
384
+ end
385
+
386
+ assert_equal([3, 1, 2], values)
387
+ end
388
+
389
+ def test_relationship_with_column_wrapper
390
+ values = nil
391
+
392
+ assert_sql(/ST_centroid\("foos"."the_geom"\)/) do
393
+ values = Foo.
394
+ st_within(
395
+ 'POLYGON((-5 -5, 5 10, 20 20, 10 5, -5 -5))',
396
+ :column => {
397
+ :wrapper => :centroid
398
+ }
399
+ ).order('id').all.collect(&:id)
400
+ end
401
+
402
+ assert_equal([1, 2, 3], values)
403
+ end
404
+
405
+ def test_relationship_with_column_wrapper_and_option
406
+ values = nil
407
+
408
+ assert_sql(/ST_geometryn\("foos"."the_geom", 1\)/) do
409
+ values = Foo.
410
+ st_within(
411
+ 'POLYGON((-5 -5, 5 10, 20 20, 10 5, -5 -5))',
412
+ :column => {
413
+ :wrapper => {
414
+ :geometryn => 1
415
+ }
416
+ }
417
+ ).order('id').all.collect(&:id)
418
+ end
419
+
420
+ assert_equal([1, 2], values)
421
+ end
422
+
423
+ def test_relationship_with_column_wrapper_and_options
424
+ values = nil
425
+
426
+ assert_sql(/ST_snap\("foos"."the_geom", 'POINT \(0 0\)', 1.0\)/) do
427
+ values = Foo.
428
+ st_within(
429
+ 'POLYGON((-5 -5, 5 10, 20 20, 10 5, -5 -5))',
430
+ :column => {
431
+ :wrapper => {
432
+ :snap => [
433
+ 'POINT (0 0)',
434
+ 1.0
435
+ ]
436
+ }
437
+ }
438
+ ).order('id').all.collect(&:id)
439
+ end
440
+
441
+ assert_equal([1, 2], values)
442
+ end
443
+ end
444
+
@@ -0,0 +1,272 @@
1
+
2
+ require 'simplecov'
3
+
4
+ SimpleCov.command_name('Unit Tests')
5
+ SimpleCov.start do
6
+ add_filter '/test/'
7
+ end
8
+
9
+ require 'rubygems'
10
+ require 'minitest/autorun'
11
+ require 'minitest/reporters'
12
+ require 'active_support'
13
+ require 'active_support/core_ext/module/aliasing'
14
+ require 'active_support/dependencies'
15
+ require 'active_record'
16
+ require 'active_record/fixtures'
17
+ require 'logger'
18
+
19
+ require File.join(File.dirname(__FILE__), %w{ .. lib activerecord-spatial })
20
+
21
+ POSTGIS_PATHS = [
22
+ ENV['POSTGIS_PATH'],
23
+ '/opt/local/share/postgresql*/contrib/postgis-*',
24
+ '/usr/share/postgresql*/contrib/postgis-*',
25
+ '/usr/pgsql-*/share/contrib/postgis-*',
26
+ ].compact
27
+
28
+ puts "Testing against ActiveRecord #{Gem.loaded_specs['activerecord'].version.to_s}"
29
+ puts "Ruby version #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} - #{RbConfig::CONFIG['RUBY_INSTALL_NAME']}"
30
+ puts "Geos library version #{Geos::VERSION}" if defined?(Geos::VERSION)
31
+ puts "GEOS version #{Geos::GEOS_VERSION}"
32
+ puts "GEOS extensions version #{Geos::GEOS_EXTENSIONS_VERSION}"
33
+ if defined?(Geos::FFIGeos)
34
+ puts "Using #{Geos::FFIGeos.geos_library_paths.join(', ')}"
35
+ end
36
+
37
+ ActiveRecord::Base.logger = Logger.new("debug.log") if ENV['ENABLE_LOGGER']
38
+ ActiveRecord::Base.configurations = {
39
+ 'arunit' => {}
40
+ }
41
+
42
+ %w{
43
+ database.yml
44
+ local_database.yml
45
+ }.each do |file|
46
+ file = File.join('test', file)
47
+
48
+ next unless File.exists?(file)
49
+
50
+ configuration = YAML.load(File.read(file))
51
+
52
+ if configuration['arunit']
53
+ ActiveRecord::Base.configurations['arunit'].merge!(configuration['arunit'])
54
+ end
55
+
56
+ if defined?(JRUBY_VERSION) && configuration['jdbc']
57
+ ActiveRecord::Base.configurations['arunit'].merge!(configuration['jdbc'])
58
+ end
59
+ end
60
+
61
+ ActiveRecord::Base.establish_connection 'arunit'
62
+ ARBC = ActiveRecord::Base.connection
63
+
64
+ if postgresql_version = ARBC.select_rows('SELECT version()').first.first
65
+ puts "PostgreSQL info from version(): #{postgresql_version}"
66
+ end
67
+
68
+ puts "Checking for PostGIS install"
69
+ 2.times do
70
+ begin
71
+ if postgis_version = ActiveRecordSpatial::POSTGIS[:lib]
72
+ puts "PostGIS info from postgis_full_version(): #{postgis_version}"
73
+ break
74
+ end
75
+ rescue ActiveRecord::StatementInvalid
76
+ puts "Trying to install PostGIS. If this doesn't work, you'll have to do this manually!"
77
+
78
+ plpgsql = ARBC.select_rows(%{SELECT count(*) FROM pg_language WHERE lanname = 'plpgsql'}).first.first.to_i
79
+ if plpgsql == 0
80
+ ARBC.execute(%{CREATE LANGUAGE plpgsql})
81
+ end
82
+
83
+ %w{
84
+ postgis.sql
85
+ spatial_ref_sys.sql
86
+ }.each do |file|
87
+ if !(found = Dir.glob(POSTGIS_PATHS).collect { |path|
88
+ File.join(path, file)
89
+ }.first)
90
+ puts "ERROR: Couldn't find #{file}. Try setting the POSTGIS_PATH to give us a hint!"
91
+ exit
92
+ else
93
+ ARBC.execute(File.read(found))
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ class ActiveRecordSpatialTestCase < ActiveRecord::TestCase
100
+ BASE_PATH = Pathname.new(File.dirname(__FILE__))
101
+
102
+ include ActiveRecord::TestFixtures
103
+ self.fixture_path = BASE_PATH.join('fixtures')
104
+
105
+ REGEXP_WKB_HEX = /[A-Fa-f0-9\s]+/
106
+
107
+ POINT_WKT = 'POINT(10 10.01)'
108
+ POINT_EWKT = 'SRID=4326; POINT(10 10.01)'
109
+ POINT_EWKT_WITH_DEFAULT = 'SRID=default; POINT(10 10.01)'
110
+ POINT_WKB = "0101000000000000000000244085EB51B81E052440"
111
+ POINT_WKB_BIN = "\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x24\x40\x85\xEB\x51\xB8\x1E\x05\x24\x40"
112
+ POINT_EWKB = "0101000020E6100000000000000000244085EB51B81E052440"
113
+ POINT_EWKB_BIN = "\x01\x01\x00\x00\x20\xE6\x10\x00\x00\x00\x00\x00\x00\x00\x00\x24\x40\x85\xEB\x51\xB8\x1E\x05\x24\x40"
114
+ POINT_G_LAT_LNG = "(10.01, 10)"
115
+ POINT_G_LAT_LNG_URL_VALUE = "10.01,10"
116
+
117
+ POLYGON_WKT = 'POLYGON((0 0, 1 1, 2.5 2.5, 5 5, 0 0))'
118
+ POLYGON_EWKT = 'SRID=4326; POLYGON((0 0, 1 1, 2.5 2.5, 5 5, 0 0))'
119
+ POLYGON_WKB = "
120
+ 0103000000010000000500000000000000000000000000000000000000000000000000F
121
+ 03F000000000000F03F0000000000000440000000000000044000000000000014400000
122
+ 00000000144000000000000000000000000000000000
123
+ ".gsub(/\s/, '')
124
+ POLYGON_WKB_BIN = [
125
+ "\x01\x03\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00",
126
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0\x3F\x00",
127
+ "\x00\x00\x00\x00\x00\xF0\x3F\x00\x00\x00\x00\x00\x00\x04\x40\x00\x00\x00\x00",
128
+ "\x00\x00\x04\x40\x00\x00\x00\x00\x00\x00\x14\x40\x00\x00\x00\x00\x00\x00\x14",
129
+ "\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
130
+ ].join
131
+ POLYGON_EWKB = "
132
+ 0103000020E610000001000000050000000000000000000000000000000000000000000
133
+ 0000000F03F000000000000F03F00000000000004400000000000000440000000000000
134
+ 1440000000000000144000000000000000000000000000000000
135
+ ".gsub(/\s/, '')
136
+ POLYGON_EWKB_BIN = [
137
+ "\x01\x03\x00\x00\x20\xE6\x10\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00",
138
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
139
+ "\x00\x00\x00\x00\x00\xF0\x3F\x00\x00\x00\x00\x00\x00\xF0\x3F\x00\x00",
140
+ "\x00\x00\x00\x00\x04\x40\x00\x00\x00\x00\x00\x00\x04\x40\x00\x00\x00",
141
+ "\x00\x00\x00\x14\x40\x00\x00\x00\x00\x00\x00\x14\x40\x00\x00\x00\x00",
142
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
143
+ ].join
144
+
145
+ POLYGON_WITH_INTERIOR_RING = "POLYGON((0 0, 5 0, 5 5, 0 5, 0 0),(4 4, 4 1, 1 1, 1 4, 4 4))"
146
+
147
+ LINESTRING_WKT = "LINESTRING (0 0, 5 5, 5 10, 10 10)"
148
+
149
+ GEOMETRYCOLLECTION_WKT = 'GEOMETRYCOLLECTION (
150
+ MULTIPOLYGON (
151
+ ((0 0, 1 0, 1 1, 0 1, 0 0)),
152
+ (
153
+ (10 10, 10 14, 14 14, 14 10, 10 10),
154
+ (11 11, 11 12, 12 12, 12 11, 11 11)
155
+ )
156
+ ),
157
+ POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)),
158
+ POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0), (4 4, 4 1, 1 1, 1 4, 4 4)),
159
+ MULTILINESTRING ((0 0, 2 3), (10 10, 3 4)),
160
+ LINESTRING (0 0, 2 3),
161
+ MULTIPOINT ((0 0), (2 3)),
162
+ POINT (9 0)
163
+ )'
164
+
165
+ BOUNDS_G_LAT_LNG = "((0.1, 0.1), (5.2, 5.2))"
166
+ BOUNDS_G_LAT_LNG_URL_VALUE = '0.1,0.1,5.2,5.2'
167
+
168
+ class << self
169
+ def load_models(*args)
170
+ options = args.extract_options!
171
+
172
+ args.each do |model|
173
+ model = model.to_s
174
+ klass = model.classify
175
+
176
+ ActiveSupport::Dependencies.load_file(BASE_PATH.join("models/#{model}.rb"), [ klass ])
177
+
178
+ ActiveRecord::Base.silence do
179
+ fixtures model.pluralize
180
+ end
181
+ end
182
+ end
183
+
184
+ def load_default_models
185
+ load_models(:foo, :bar)
186
+
187
+ Foo.class_eval do
188
+ has_many_spatially :foos
189
+ has_many_spatially :bars
190
+ end
191
+
192
+ Bar.class_eval do
193
+ has_many_spatially :foos
194
+ has_many_spatially :bars
195
+ end
196
+ end
197
+
198
+ def after_suite
199
+ ActiveSupport::Dependencies.clear
200
+ end
201
+ end
202
+
203
+ def setup
204
+ if ActiveRecord::Base.logger
205
+ ActiveRecord::Base.logger.debug("Beginning tests for #{self.class.name}##{self.method_name}")
206
+ end
207
+ end
208
+
209
+ def assert_saneness_of_point(point)
210
+ assert_kind_of(Geos::Point, point)
211
+ assert_equal(10.01, point.lat)
212
+ assert_equal(10, point.lng)
213
+ end
214
+
215
+ def assert_saneness_of_polygon(polygon)
216
+ assert_kind_of(Geos::Polygon, polygon)
217
+ cs = polygon.exterior_ring.coord_seq
218
+ assert_equal([
219
+ [ 0, 0 ],
220
+ [ 1, 1 ],
221
+ [ 2.5, 2.5 ],
222
+ [ 5, 5 ],
223
+ [ 0, 0 ]
224
+ ], cs.to_a)
225
+ end
226
+ end
227
+
228
+ module ActiveRecord
229
+ class SQLCounter
230
+ cattr_accessor :ignored_sql
231
+ self.ignored_sql = [
232
+ /^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/,
233
+ /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/,
234
+ /^SHOW max_identifier_length/, /^BEGIN/, /^COMMIT/, /^ROLLBACK/, /\WFROM pg_/
235
+ ]
236
+
237
+ cattr_accessor :log
238
+ self.log = []
239
+
240
+ attr_reader :ignore
241
+
242
+ def initialize(ignore = self.class.ignored_sql)
243
+ @ignore = ignore
244
+ end
245
+
246
+ def call(name, start, finish, message_id, values)
247
+ sql = values[:sql]
248
+
249
+ # FIXME: this seems bad. we should probably have a better way to indicate
250
+ # the query was cached
251
+ return if 'CACHE' == values[:name] || ignore.any? { |x| x =~ sql }
252
+ self.class.log << sql
253
+ end
254
+ end
255
+
256
+ ActiveSupport::Notifications.subscribe('sql.active_record', SQLCounter.new)
257
+ end
258
+
259
+ class SpatialTestRunner < MiniTest::Reporters::SpecReporter
260
+ def before_suite(suite)
261
+ super(suite)
262
+ suite.before_suite if suite.respond_to?(:before_suite)
263
+ end
264
+
265
+ def after_suite(suite)
266
+ super(suite)
267
+ suite.after_suite if suite.respond_to?(:after_suite)
268
+ end
269
+ end
270
+
271
+ MiniTest::Reporters.use!(SpatialTestRunner.new)
272
+