activerecord-spatial 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+