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
data/test/database.yml ADDED
@@ -0,0 +1,17 @@
1
+ ---
2
+ # To modify the test database parameters, create a new file called
3
+ # local_database.yml and go nuts with settings. The "jdbc" settings
4
+ # are merged into the "arunit" settings as JDBC works over a TCP
5
+ # socket and those sorts of connections generally require some user
6
+ # credentials.
7
+
8
+ arunit:
9
+ adapter: "postgresql"
10
+ database: "activerecord_spatial_unit_tests"
11
+ min_messages: "warning"
12
+ schema_search_path: "public"
13
+
14
+ jdbc:
15
+ host: "localhost"
16
+ adapter: "jdbcpostgresql"
17
+
@@ -0,0 +1,16 @@
1
+ ---
2
+ bars_1:
3
+ id: 1
4
+ name: "one"
5
+ the_geom: 'POINT(5 5)'
6
+ the_other_geom: 'SRID=4326; POINT(15 15)'
7
+ bars_2:
8
+ id: 2
9
+ name: "two"
10
+ the_geom: 'POINT(15 15)'
11
+ the_other_geom: 'SRID=4326; POINT(25 25)'
12
+ bars_3:
13
+ id: 3
14
+ name: "three"
15
+ the_geom: 'POLYGON((-10 -10, -10 10, 10 10, 10 -10, -10 -10))'
16
+ the_other_geom: 'SRID=4326; POLYGON((-10 -10, -10 10, 10 10, 10 -10, -10 -10))'
@@ -0,0 +1,37 @@
1
+ ---
2
+ blorts_1:
3
+ id: 1
4
+ name: "foo 1-1"
5
+ foo_id: 1
6
+ blorts_2:
7
+ id: 2
8
+ name: "foo 1-2"
9
+ foo_id: 1
10
+ blorts_3:
11
+ id: 3
12
+ name: "foo 1-3"
13
+ foo_id: 1
14
+ blorts_4:
15
+ id: 4
16
+ name: "foo 2-1"
17
+ foo_id: 2
18
+ blorts_5:
19
+ id: 5
20
+ name: "foo 2-2"
21
+ foo_id: 2
22
+ blorts_6:
23
+ id: 6
24
+ name: "foo 2-3"
25
+ foo_id: 2
26
+ blorts_7:
27
+ id: 7
28
+ name: "foo 3-1"
29
+ foo_id: 3
30
+ blorts_8:
31
+ id: 8
32
+ name: "foo 3-2"
33
+ foo_id: 3
34
+ blorts_9:
35
+ id: 9
36
+ name: "foo 3-3"
37
+ foo_id: 3
@@ -0,0 +1,17 @@
1
+ ---
2
+ one:
3
+ id: 1
4
+ name: "one"
5
+ the_geom: 'POINT(0 0 0)'
6
+ the_other_geom: 'SRID=4326; POINT(10 10 10)'
7
+ two:
8
+ id: 2
9
+ name: "two"
10
+ the_geom: 'POINT(10 10 10)'
11
+ the_other_geom: 'SRID=4326; POINT(20 20 20)'
12
+ three:
13
+ id: 3
14
+ name: "three"
15
+ the_geom: 'POLYGON((-5 -5 -5, -5 5 5, 5 5 5, 5 -5 -5, -5 -5 -5))'
16
+ the_other_geom: 'SRID=4326; POLYGON((5 5 5, 5 10 10, 10 10 10, 10 5 5, 5 5 5))'
17
+
@@ -0,0 +1,16 @@
1
+ ---
2
+ one:
3
+ id: 1
4
+ name: "one"
5
+ the_geom: 'POINT(0 0)'
6
+ the_other_geom: 'SRID=4326; POINT(10 10)'
7
+ two:
8
+ id: 2
9
+ name: "two"
10
+ the_geom: 'POINT(10 10)'
11
+ the_other_geom: 'SRID=4326; POINT(20 20)'
12
+ three:
13
+ id: 3
14
+ name: "three"
15
+ the_geom: 'POLYGON((-5 -5, -5 5, 5 5, 5 -5, -5 -5))'
16
+ the_other_geom: 'SRID=4326; POLYGON((5 5, 5 10, 10 10, 10 5, 5 5))'
@@ -0,0 +1,16 @@
1
+ ---
2
+ foos_1:
3
+ id: 1
4
+ name: "one"
5
+ the_geom: 'POINT(0 0)'
6
+ the_other_geom: 'SRID=4326; POINT(10 10)'
7
+ foos_2:
8
+ id: 2
9
+ name: "two"
10
+ the_geom: 'POINT(10 10)'
11
+ the_other_geom: 'SRID=4326; POINT(20 20)'
12
+ foos_3:
13
+ id: 3
14
+ name: "three"
15
+ the_geom: 'POLYGON((-5 -5, -5 5, 5 5, 5 -5, -5 -5))'
16
+ the_other_geom: 'SRID=4326; POLYGON((5 5, 5 10, 10 10, 10 5, 5 5))'
@@ -0,0 +1,36 @@
1
+ ---
2
+ zortable_1:
3
+ id: 1
4
+ name: "zortable 1-1"
5
+ zortable_geom: "010100000000000000000000000000000000000000"
6
+ zortable_type: "Foo"
7
+ zortable_2:
8
+ id: 2
9
+ name: "zortable 1-2"
10
+ zortable_geom: "010100000000000000000014400000000000001440"
11
+ zortable_type: "Foo"
12
+ zortable_3:
13
+ id: 3
14
+ name: "zortable 1-3"
15
+ zortable_geom: "01010000000000000000002E400000000000002E40"
16
+ zortable_type: "Foo"
17
+ zortable_4:
18
+ id: 4
19
+ name: "zortable 2-1"
20
+ zortable_geom: "010100000000000000000000000000000000000000"
21
+ zortable_type: "Bar"
22
+ zortable_5:
23
+ id: 5
24
+ name: "zortable 2-2"
25
+ zortable_geom: "010100000000000000000014400000000000001440"
26
+ zortable_type: "Bar"
27
+ zortable_6:
28
+ id: 6
29
+ name: "zortable 2-3"
30
+ zortable_geom: "01010000000000000000002E400000000000002E40"
31
+ zortable_type: "Bar"
32
+ zortable_7:
33
+ id: 7
34
+ name: "big zortable"
35
+ zortable_geom: "0103000000010000000500000000000000000034C000000000000034C000000000000034C0000000000000344000000000000034400000000000003440000000000000344000000000000034C000000000000034C000000000000034C0"
36
+ zortable_type: "Foo"
@@ -0,0 +1,40 @@
1
+
2
+ $: << File.dirname(__FILE__)
3
+ require 'test_helper'
4
+
5
+ class GeographyColumnTests < ActiveRecordSpatialTestCase
6
+ def self.before_suite
7
+ load_models(:foo_geography)
8
+ end
9
+
10
+ def test_geography_columns_detected
11
+ assert_equal(0, FooGeography.geometry_columns.length)
12
+ assert_equal(2, FooGeography.geography_columns.length)
13
+
14
+ FooGeography.geography_columns.each do |column|
15
+ assert_kind_of(ActiveRecordSpatial::GeographyColumn, column)
16
+ end
17
+ end
18
+
19
+ def test_srid_for
20
+ assert_equal(ActiveRecordSpatial::UNKNOWN_SRIDS[:geography], FooGeography.srid_for(:the_geom))
21
+ assert_equal(4326, FooGeography.srid_for(:the_other_geom))
22
+ end
23
+
24
+ def test_coord_dimension_for
25
+ assert_equal(2, FooGeography.coord_dimension_for(:the_geom))
26
+ assert_equal(2, FooGeography.coord_dimension_for(:the_other_geom))
27
+ end
28
+
29
+ def test_geography_column_by_name
30
+ assert_kind_of(ActiveRecordSpatial::GeographyColumn, FooGeography.geography_column_by_name(:the_geom))
31
+ assert_kind_of(ActiveRecordSpatial::GeographyColumn, FooGeography.geography_column_by_name(:the_other_geom))
32
+ end
33
+
34
+ def test_spatial_ref_sys
35
+ assert_nil(FooGeography.geography_column_by_name(:the_geom).spatial_ref_sys)
36
+ assert_kind_of(ActiveRecordSpatial::SpatialRefSys, FooGeography.geography_column_by_name(:the_other_geom).spatial_ref_sys)
37
+ assert_equal(4326, FooGeography.geography_column_by_name(:the_other_geom).spatial_ref_sys.srid)
38
+ end
39
+ end
40
+
@@ -0,0 +1,40 @@
1
+
2
+ $: << File.dirname(__FILE__)
3
+ require 'test_helper'
4
+
5
+ class GeometryColumnTests < ActiveRecordSpatialTestCase
6
+ def self.before_suite
7
+ load_models(:foo)
8
+ end
9
+
10
+ def test_geometry_columns_detected
11
+ assert_equal(2, Foo.geometry_columns.length)
12
+ assert_equal(0, Foo.geography_columns.length)
13
+
14
+ Foo.geometry_columns.each do |column|
15
+ assert_kind_of(ActiveRecordSpatial::GeometryColumn, column)
16
+ end
17
+ end
18
+
19
+ def test_srid_for
20
+ assert_equal(ActiveRecordSpatial::UNKNOWN_SRID, Foo.srid_for(:the_geom))
21
+ assert_equal(4326, Foo.srid_for(:the_other_geom))
22
+ end
23
+
24
+ def test_coord_dimension_for
25
+ assert_equal(2, Foo.coord_dimension_for(:the_geom))
26
+ assert_equal(2, Foo.coord_dimension_for(:the_other_geom))
27
+ end
28
+
29
+ def test_geometry_column_by_name
30
+ assert_kind_of(ActiveRecordSpatial::GeometryColumn, Foo.geometry_column_by_name(:the_geom))
31
+ assert_kind_of(ActiveRecordSpatial::GeometryColumn, Foo.geometry_column_by_name(:the_other_geom))
32
+ end
33
+
34
+ def test_spatial_ref_sys
35
+ assert_nil(Foo.geometry_column_by_name(:the_geom).spatial_ref_sys)
36
+ assert_kind_of(ActiveRecordSpatial::SpatialRefSys, Foo.geometry_column_by_name(:the_other_geom).spatial_ref_sys)
37
+ assert_equal(4326, Foo.geometry_column_by_name(:the_other_geom).spatial_ref_sys.srid)
38
+ end
39
+ end
40
+
@@ -0,0 +1,17 @@
1
+
2
+ if !ARBC.table_exists?('bars')
3
+ ActiveRecord::Migration.create_table(:bars) do |t|
4
+ t.text :name
5
+ end
6
+
7
+ ARBC.execute(%{SELECT AddGeometryColumn('public', 'bars', 'the_geom', #{ActiveRecordSpatial::UNKNOWN_SRID}, 'GEOMETRY', 2)})
8
+ ARBC.execute(%{SELECT AddGeometryColumn('public', 'bars', 'the_other_geom', 4326, 'GEOMETRY', 2)})
9
+ end
10
+
11
+ class Bar < ActiveRecord::Base
12
+ include ActiveRecordSpatial::SpatialColumns
13
+ include ActiveRecordSpatial::SpatialScopes
14
+
15
+ self.create_spatial_column_accessors!
16
+ end
17
+
@@ -0,0 +1,12 @@
1
+
2
+ if !ARBC.table_exists?('blorts')
3
+ ActiveRecord::Migration.create_table(:blorts) do |t|
4
+ t.text :name
5
+ t.integer :foo_id
6
+ end
7
+ end
8
+
9
+ class Blort < ActiveRecord::Base
10
+ belongs_to :foo
11
+ end
12
+
@@ -0,0 +1,17 @@
1
+
2
+ if !ARBC.table_exists?('foos')
3
+ ActiveRecord::Migration.create_table(:foos) do |t|
4
+ t.text :name
5
+ end
6
+
7
+ ARBC.execute(%{SELECT AddGeometryColumn('public', 'foos', 'the_geom', #{ActiveRecordSpatial::UNKNOWN_SRID}, 'GEOMETRY', 2)})
8
+ ARBC.execute(%{SELECT AddGeometryColumn('public', 'foos', 'the_other_geom', 4326, 'GEOMETRY', 2)})
9
+ end
10
+
11
+ class Foo < ActiveRecord::Base
12
+ include ActiveRecordSpatial::SpatialColumns
13
+ include ActiveRecordSpatial::SpatialScopes
14
+
15
+ self.create_spatial_column_accessors!
16
+ end
17
+
@@ -0,0 +1,17 @@
1
+
2
+ if !ARBC.table_exists?('foo3ds')
3
+ ActiveRecord::Migration.create_table(:foo3ds) do |t|
4
+ t.text :name
5
+ end
6
+
7
+ ARBC.execute(%{SELECT AddGeometryColumn('public', 'foo3ds', 'the_geom', #{ActiveRecordSpatial::UNKNOWN_SRID}, 'GEOMETRY', 3)})
8
+ ARBC.execute(%{SELECT AddGeometryColumn('public', 'foo3ds', 'the_other_geom', 4326, 'GEOMETRY', 3)})
9
+ end
10
+
11
+ class Foo3d < ActiveRecord::Base
12
+ include ActiveRecordSpatial::SpatialColumns
13
+ include ActiveRecordSpatial::SpatialScopes
14
+
15
+ self.create_spatial_column_accessors!
16
+ end
17
+
@@ -0,0 +1,16 @@
1
+
2
+ if !ARBC.table_exists?('foo_geographies')
3
+ ActiveRecord::Migration.create_table(:foo_geographies) do |t|
4
+ t.text :name
5
+ t.column :the_geom, :geography
6
+ t.column :the_other_geom, 'geography(Geometry, 4326)'
7
+ end
8
+ end
9
+
10
+ class FooGeography < ActiveRecord::Base
11
+ include ActiveRecordSpatial::SpatialColumns
12
+ include ActiveRecordSpatial::SpatialScopes
13
+
14
+ self.create_spatial_column_accessors!
15
+ end
16
+
@@ -0,0 +1,17 @@
1
+
2
+ if !ARBC.table_exists?('zortables')
3
+ ActiveRecord::Migration.create_table(:zortables) do |t|
4
+ t.text :name
5
+ t.text :zortable_type
6
+ end
7
+
8
+ ARBC.execute(%{SELECT AddGeometryColumn('public', 'zortables', 'zortable_geom', #{ActiveRecordSpatial::UNKNOWN_SRID}, 'GEOMETRY', 2)})
9
+ end
10
+
11
+ class Zortable < ActiveRecord::Base
12
+ include ActiveRecordSpatial::SpatialColumns
13
+ include ActiveRecordSpatial::SpatialScopes
14
+
15
+ self.create_spatial_column_accessors!
16
+ end
17
+
@@ -0,0 +1,106 @@
1
+
2
+ $: << File.dirname(__FILE__)
3
+ require 'test_helper'
4
+
5
+ class SpatialScopesGeographiesTests < ActiveRecordSpatialTestCase
6
+ def self.before_suite
7
+ load_models(:foo_geography)
8
+ end
9
+
10
+ def ids_tester(method, args, ids = [], options = {})
11
+ geoms = FooGeography.send(method, *Array.wrap(args)).all(options)
12
+ assert_equal(ids.sort, geoms.collect(&:id).sort)
13
+ end
14
+
15
+ def test_covers
16
+ ids_tester(:st_covers, 'POINT(0 0)', [ 3 ], :conditions => {
17
+ :id => [ 3 ]
18
+ })
19
+ end
20
+
21
+ def test_coveredby
22
+ ids_tester(:st_coveredby, 'POLYGON((-6 -6, -6 6, 6 6, 6 -6, -6 -6))', [ 1 ], :conditions => {
23
+ :id => [ 1, 2 ]
24
+ })
25
+ end
26
+
27
+ def test_intersects
28
+ ids_tester(:st_intersects, 'LINESTRING(-5 -5, 10 10)', [ 2, 3 ])
29
+ end
30
+
31
+ def test_dwithin
32
+ ids_tester(:st_dwithin, [ 'POINT(5 5)', 10 ], [ 3 ])
33
+ end
34
+
35
+ def test_allow_null
36
+ begin
37
+ foo = FooGeography.create(:name => 'four')
38
+ ids_tester(:st_covers, [ 'POINT(3 3)', { :allow_null => true } ], [ 3, foo.id ])
39
+ ensure
40
+ FooGeography.find_by_name('four').destroy
41
+ end
42
+ end
43
+
44
+ def test_with_column
45
+ assert_equal([3], FooGeography.st_covers('POINT(7 7)', :column => :the_other_geom).all.collect(&:id).sort)
46
+ end
47
+
48
+ def test_with_srid_switching
49
+ assert_equal([3], FooGeography.st_covers('SRID=4326; POINT(3 3)').all.collect(&:id).sort)
50
+ end
51
+
52
+ def test_with_srid_default
53
+ assert_equal([3], FooGeography.st_covers('SRID=default; POINT(3 3)').all.collect(&:id).sort)
54
+ end
55
+
56
+ def test_with_srid_transform
57
+ assert_equal([3], FooGeography.st_covers('SRID=4269; POINT(7 7)', :column => :the_other_geom).all.collect(&:id).sort)
58
+ end
59
+
60
+ def test_order_by_st_distance
61
+ assert_equal([3, 1, 2], FooGeography.order_by_st_distance('POINT(1 1)').all.collect(&:id))
62
+ end
63
+
64
+ def test_order_by_st_distance_desc
65
+ assert_equal([2, 1, 3], FooGeography.order_by_st_distance('POINT(1 1)', :desc => true).all.collect(&:id))
66
+ end
67
+
68
+ def test_order_by_st_area
69
+ assert_equal([1, 2, 3], FooGeography.order_by_st_area.order('id').all.collect(&:id))
70
+ end
71
+
72
+ def test_order_by_st_area_desc
73
+ assert_equal([3, 1, 2], FooGeography.order_by_st_area(:desc => true).order('id').all.collect(&:id))
74
+ end
75
+
76
+ def test_order_by_st_length
77
+ assert_equal([1, 2, 3], FooGeography.order_by_st_length.order('id').all.collect(&:id))
78
+ end
79
+
80
+ def test_order_by_st_length_desc
81
+ expected = if ActiveRecordSpatial::POSTGIS[:lib] >= '2.0'
82
+ [1, 2, 3]
83
+ else
84
+ [3, 1, 2]
85
+ end
86
+
87
+ assert_equal(expected, FooGeography.order_by_st_length(:desc => true).order('id').where('true = true').all.collect(&:id))
88
+ end
89
+
90
+ def test_order_by_st_perimeter
91
+ skip('requires PostGIS 2+') unless FooGeography.respond_to?(:order_by_st_perimeter)
92
+
93
+ assert_equal([1, 2, 3], FooGeography.order_by_st_perimeter.order('id').all.collect(&:id))
94
+ end
95
+
96
+ def test_order_by_st_perimeter_desc
97
+ skip('requires PostGIS 2+') unless FooGeography.respond_to?(:order_by_st_perimeter)
98
+
99
+ assert_equal([3, 1, 2], FooGeography.order_by_st_perimeter(:desc => true).order('id').all.collect(&:id))
100
+ end
101
+
102
+ def test_order_by_st_area_with_desc_symbol
103
+ assert_equal([3, 1, 2], FooGeography.order_by_st_area(:desc).order('id').all.collect(&:id))
104
+ end
105
+ end
106
+