activerecord-postgis-adapter 2.0.2 → 2.1.0
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.
- checksums.yaml +4 -4
- data/lib/active_record/connection_adapters/postgis_adapter.rb +9 -8
- data/lib/active_record/connection_adapters/postgis_adapter/common_adapter_methods.rb +6 -6
- data/lib/active_record/connection_adapters/postgis_adapter/main_adapter.rb +18 -33
- data/lib/active_record/connection_adapters/postgis_adapter/spatial_column.rb +12 -8
- data/lib/active_record/connection_adapters/postgis_adapter/spatial_column_info.rb +42 -0
- data/lib/active_record/connection_adapters/postgis_adapter/version.rb +1 -1
- data/test/basic_test.rb +175 -183
- data/test/ddl_test.rb +248 -217
- data/test/nested_class_test.rb +22 -30
- data/test/setup_test.rb +4 -12
- data/test/spatial_queries_test.rb +83 -91
- data/test/tasks_test.rb +145 -153
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9072742044be5bdca4d15241b2e55fd59753f07f
|
4
|
+
data.tar.gz: f2f0227789eb674f799d1dee7f85555e1040d4e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fde41e0dcd38d4a6d2a7a53f739e50610c998682bb0f5303383e580269ce486ec15fa45aaa698fa5d71e7d943ff404785cb5bf96d785d329877f54d08a0f8732
|
7
|
+
data.tar.gz: f8fe668e18334aefef68f4762e5da778d3b3d4929cab9c1d065a17e55ea392f51954406f643cf47b7021c1372ef3dc42bba397f9d2cc4742bd7718561fb5bc1f
|
@@ -16,15 +16,16 @@ require 'active_record'
|
|
16
16
|
require 'active_record/connection_adapters/postgresql_adapter'
|
17
17
|
require 'rgeo/active_record'
|
18
18
|
|
19
|
-
require 'active_record/connection_adapters/postgis_adapter/version
|
20
|
-
require 'active_record/connection_adapters/postgis_adapter/common_adapter_methods
|
21
|
-
require 'active_record/connection_adapters/postgis_adapter/main_adapter
|
22
|
-
require 'active_record/connection_adapters/postgis_adapter/
|
23
|
-
require 'active_record/connection_adapters/postgis_adapter/
|
24
|
-
require 'active_record/connection_adapters/postgis_adapter/
|
25
|
-
require 'active_record/connection_adapters/postgis_adapter/
|
19
|
+
require 'active_record/connection_adapters/postgis_adapter/version'
|
20
|
+
require 'active_record/connection_adapters/postgis_adapter/common_adapter_methods'
|
21
|
+
require 'active_record/connection_adapters/postgis_adapter/main_adapter'
|
22
|
+
require 'active_record/connection_adapters/postgis_adapter/spatial_column_info'
|
23
|
+
require 'active_record/connection_adapters/postgis_adapter/spatial_table_definition'
|
24
|
+
require 'active_record/connection_adapters/postgis_adapter/spatial_column'
|
25
|
+
require 'active_record/connection_adapters/postgis_adapter/arel_tosql'
|
26
|
+
require 'active_record/connection_adapters/postgis_adapter/setup'
|
26
27
|
require 'active_record/connection_adapters/postgis_adapter/create_connection'
|
27
|
-
require 'active_record/connection_adapters/postgis_adapter/postgis_database_tasks
|
28
|
+
require 'active_record/connection_adapters/postgis_adapter/postgis_database_tasks'
|
28
29
|
|
29
30
|
::ActiveRecord::ConnectionAdapters::PostGISAdapter.initial_setup
|
30
31
|
|
@@ -2,7 +2,7 @@ module ActiveRecord # :nodoc:
|
|
2
2
|
module ConnectionAdapters # :nodoc:
|
3
3
|
module PostGISAdapter # :nodoc:
|
4
4
|
SPATIAL_COLUMN_CONSTRUCTORS = ::RGeo::ActiveRecord::DEFAULT_SPATIAL_COLUMN_CONSTRUCTORS.merge(
|
5
|
-
:
|
5
|
+
geography: { type: 'geometry', geographic: true }
|
6
6
|
)
|
7
7
|
|
8
8
|
# http://postgis.17.x6.nabble.com/Default-SRID-td5001115.html
|
@@ -31,16 +31,16 @@ module ActiveRecord # :nodoc:
|
|
31
31
|
|
32
32
|
def srs_database_columns
|
33
33
|
{
|
34
|
-
:
|
35
|
-
:
|
36
|
-
:
|
37
|
-
:
|
34
|
+
auth_name_column: 'auth_name',
|
35
|
+
auth_srid_column: 'auth_srid',
|
36
|
+
proj4text_column: 'proj4text',
|
37
|
+
srtext_column: 'srtext',
|
38
38
|
}
|
39
39
|
end
|
40
40
|
|
41
41
|
def quote(value, column=nil)
|
42
42
|
if ::RGeo::Feature::Geometry.check_type(value)
|
43
|
-
"'#{::RGeo::WKRep::WKBGenerator.new(:
|
43
|
+
"'#{::RGeo::WKRep::WKBGenerator.new(hex_format: true, type_format: :ewkb, emit_ewkb_srid: true).generate(value)}'"
|
44
44
|
elsif value.is_a?(::RGeo::Cartesian::BoundingBox)
|
45
45
|
"'#{value.min_x},#{value.min_y},#{value.max_x},#{value.max_y}'::box"
|
46
46
|
else
|
@@ -15,13 +15,14 @@ module ActiveRecord # :nodoc:
|
|
15
15
|
def native_database_types
|
16
16
|
# Overridden to add the :spatial type
|
17
17
|
@@native_database_types ||= super.merge(
|
18
|
-
:
|
19
|
-
:
|
18
|
+
geography: { name: 'geography' },
|
19
|
+
spatial: { name: 'geometry' },
|
20
|
+
)
|
20
21
|
end
|
21
22
|
|
22
23
|
def type_cast(value, column, array_member = false)
|
23
24
|
if ::RGeo::Feature::Geometry.check_type(value)
|
24
|
-
::RGeo::WKRep::WKBGenerator.new(:
|
25
|
+
::RGeo::WKRep::WKBGenerator.new(hex_format: true, type_format: :ewkb, emit_ewkb_srid: true).generate(value)
|
25
26
|
else
|
26
27
|
super
|
27
28
|
end
|
@@ -30,8 +31,8 @@ module ActiveRecord # :nodoc:
|
|
30
31
|
# FULL REPLACEMENT. RE-CHECK ON NEW VERSIONS
|
31
32
|
# https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
|
32
33
|
def columns(table_name, name = nil)
|
34
|
+
column_info = SpatialColumnInfo.new(self, quote_string(table_name.to_s))
|
33
35
|
# Limit, precision, and scale are all handled by the superclass.
|
34
|
-
spatial_info_ = spatial_column_info(table_name)
|
35
36
|
column_definitions(table_name).map do |column_name, type, default, notnull, oid, fmod|
|
36
37
|
oid = column_type_map.fetch(oid.to_i, fmod.to_i) { OID::Identity.new }
|
37
38
|
SpatialColumn.new(@rgeo_factory_settings,
|
@@ -41,7 +42,7 @@ module ActiveRecord # :nodoc:
|
|
41
42
|
oid,
|
42
43
|
type,
|
43
44
|
notnull == 'f',
|
44
|
-
|
45
|
+
column_info.get(column_name, type))
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
@@ -112,12 +113,15 @@ module ActiveRecord # :nodoc:
|
|
112
113
|
table_definition = td
|
113
114
|
end
|
114
115
|
table_definition.non_geographic_spatial_columns.each do |col|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
116
|
+
options = {
|
117
|
+
has_m: col.has_m?,
|
118
|
+
has_z: col.has_z?,
|
119
|
+
srid: col.srid,
|
120
|
+
type: col.spatial_type,
|
121
|
+
}
|
122
|
+
column_name = col.name.to_s
|
123
|
+
|
124
|
+
add_spatial_column(table_name, column_name, options)
|
121
125
|
end
|
122
126
|
end
|
123
127
|
|
@@ -125,7 +129,7 @@ module ActiveRecord # :nodoc:
|
|
125
129
|
table_name = table_name.to_s
|
126
130
|
column_name = column_name.to_s
|
127
131
|
if (info = spatial_column_constructor(type.to_sym))
|
128
|
-
add_spatial_column(
|
132
|
+
add_spatial_column(table_name, column_name, info, type, options)
|
129
133
|
else
|
130
134
|
super
|
131
135
|
end
|
@@ -154,30 +158,12 @@ module ActiveRecord # :nodoc:
|
|
154
158
|
end
|
155
159
|
|
156
160
|
def spatial_column_info(table_name)
|
157
|
-
|
158
|
-
result = {}
|
159
|
-
info.each do |row|
|
160
|
-
name = row[0]
|
161
|
-
type = row[3]
|
162
|
-
dimension = row[1].to_i
|
163
|
-
has_m = !!(type =~ /m$/i)
|
164
|
-
type.sub!(/m$/, '')
|
165
|
-
has_z = dimension > 3 || dimension == 3 && !has_m
|
166
|
-
result[name] = {
|
167
|
-
:name => name,
|
168
|
-
:type => type,
|
169
|
-
:dimension => dimension,
|
170
|
-
:srid => row[2].to_i,
|
171
|
-
:has_z => has_z,
|
172
|
-
:has_m => has_m,
|
173
|
-
}
|
174
|
-
end
|
175
|
-
result
|
161
|
+
SpatialColumnInfo.new(self, quote_string(table_name.to_s)).all
|
176
162
|
end
|
177
163
|
|
178
164
|
private
|
179
165
|
|
180
|
-
def add_spatial_column(
|
166
|
+
def add_spatial_column(table_name, column_name, info = {}, type = nil, options)
|
181
167
|
limit = options[:limit]
|
182
168
|
options.merge!(limit) if limit.is_a?(::Hash)
|
183
169
|
type = (options[:type] || info[:type] || type).to_s.gsub('_', '').upcase
|
@@ -211,7 +197,6 @@ module ActiveRecord # :nodoc:
|
|
211
197
|
dimensions += 1 if has_m
|
212
198
|
dimensions
|
213
199
|
end
|
214
|
-
|
215
200
|
end
|
216
201
|
end
|
217
202
|
end
|
@@ -3,7 +3,7 @@ module ActiveRecord # :nodoc:
|
|
3
3
|
module PostGISAdapter # :nodoc:
|
4
4
|
class SpatialColumn < ConnectionAdapters::PostgreSQLColumn # :nodoc:
|
5
5
|
|
6
|
-
def initialize(factory_settings, table_name, name, default, oid_type, sql_type=nil, null=true, opts=nil)
|
6
|
+
def initialize(factory_settings, table_name, name, default, oid_type, sql_type = nil, null = true, opts = nil)
|
7
7
|
@factory_settings = factory_settings
|
8
8
|
@table_name = table_name
|
9
9
|
@geographic = !!(sql_type =~ /geography/i)
|
@@ -42,12 +42,12 @@ module ActiveRecord # :nodoc:
|
|
42
42
|
super(name, default, oid_type, sql_type, null)
|
43
43
|
if spatial?
|
44
44
|
if @srid
|
45
|
-
@limit = {:
|
45
|
+
@limit = { srid: @srid, type: @geometric_type.type_name.underscore }
|
46
46
|
@limit[:has_z] = true if @has_z
|
47
47
|
@limit[:has_m] = true if @has_m
|
48
48
|
@limit[:geographic] = true if @geographic
|
49
49
|
else
|
50
|
-
@limit = {:
|
50
|
+
@limit = { no_constraints: true }
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -91,8 +91,12 @@ module ActiveRecord # :nodoc:
|
|
91
91
|
|
92
92
|
def self.convert_to_geometry(input, factory_settings, table_name, column, geographic, srid, has_z, has_m)
|
93
93
|
if srid
|
94
|
-
constraints = {
|
95
|
-
:
|
94
|
+
constraints = {
|
95
|
+
geographic: geographic,
|
96
|
+
has_z_coordinate: has_z,
|
97
|
+
has_m_coordinate: has_m,
|
98
|
+
srid: srid
|
99
|
+
}
|
96
100
|
else
|
97
101
|
constraints = nil
|
98
102
|
end
|
@@ -107,9 +111,9 @@ module ActiveRecord # :nodoc:
|
|
107
111
|
factory = factory_settings.get_column_factory(table_name, column, constraints)
|
108
112
|
marker = input[0,1]
|
109
113
|
if marker == "\x00" || marker == "\x01" || input[0,4] =~ /[0-9a-fA-F]{4}/
|
110
|
-
::RGeo::WKRep::WKBParser.new(factory, :
|
114
|
+
::RGeo::WKRep::WKBParser.new(factory, support_ewkb: true).parse(input) rescue nil
|
111
115
|
else
|
112
|
-
::RGeo::WKRep::WKTParser.new(factory, :
|
116
|
+
::RGeo::WKRep::WKTParser.new(factory, support_ewkt: true).parse(input) rescue nil
|
113
117
|
end
|
114
118
|
end
|
115
119
|
else
|
@@ -129,7 +133,7 @@ module ActiveRecord # :nodoc:
|
|
129
133
|
|
130
134
|
def type_cast(value)
|
131
135
|
return if value.nil?
|
132
|
-
::RGeo::WKRep::WKBParser.new(@factory_generator, :
|
136
|
+
::RGeo::WKRep::WKBParser.new(@factory_generator, support_ewkb: true).parse(value) rescue nil
|
133
137
|
end
|
134
138
|
|
135
139
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ActiveRecord # :nodoc:
|
2
|
+
module ConnectionAdapters # :nodoc:
|
3
|
+
module PostGISAdapter
|
4
|
+
# Do spatial sql queries for column info and memoize that info.
|
5
|
+
class SpatialColumnInfo
|
6
|
+
def initialize(adapter, table_name)
|
7
|
+
@adapter = adapter
|
8
|
+
@table_name = table_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def all
|
12
|
+
info = @adapter.query("SELECT f_geometry_column,coord_dimension,srid,type FROM geometry_columns WHERE f_table_name='#{@table_name}'")
|
13
|
+
result = {}
|
14
|
+
info.each do |row|
|
15
|
+
name = row[0]
|
16
|
+
type = row[3]
|
17
|
+
dimension = row[1].to_i
|
18
|
+
has_m = !!(type =~ /m$/i)
|
19
|
+
type.sub!(/m$/, '')
|
20
|
+
has_z = dimension > 3 || dimension == 3 && !has_m
|
21
|
+
result[name] = {
|
22
|
+
dimension: dimension,
|
23
|
+
has_m: has_m,
|
24
|
+
has_z: has_z,
|
25
|
+
name: name,
|
26
|
+
srid: row[2].to_i,
|
27
|
+
type: type,
|
28
|
+
}
|
29
|
+
end
|
30
|
+
result
|
31
|
+
end
|
32
|
+
|
33
|
+
# will not query the database for non-spatial columns/tables
|
34
|
+
def get(column_name, type)
|
35
|
+
return nil unless type =~ /geometry/i
|
36
|
+
@spatial_column_info ||= all
|
37
|
+
@spatial_column_info[column_name]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/test/basic_test.rb
CHANGED
@@ -1,190 +1,182 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
when :no_constraints
|
27
|
-
klass.connection.create_table(:spatial_test) do |t_|
|
28
|
-
t_.column 'geo', :geometry, :no_constraints => true
|
29
|
-
end
|
30
|
-
end
|
31
|
-
klass
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_version
|
35
|
-
refute_nil ::ActiveRecord::ConnectionAdapters::PostGISAdapter::VERSION
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_postgis_available
|
39
|
-
connection = create_ar_class.connection
|
40
|
-
assert_equal 'PostGIS', connection.adapter_name
|
41
|
-
refute_nil connection.postgis_lib_version
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_set_and_get_point
|
45
|
-
klass = populate_ar_class(:mercator_point)
|
46
|
-
obj = klass.new
|
47
|
-
assert_nil obj.latlon
|
48
|
-
obj.latlon = @factory.point(1.0, 2.0)
|
49
|
-
assert_equal @factory.point(1.0, 2.0), obj.latlon
|
50
|
-
assert_equal 3785, obj.latlon.srid
|
51
|
-
end
|
52
|
-
|
53
|
-
def test_set_and_get_point_from_wkt
|
54
|
-
klass = populate_ar_class(:mercator_point)
|
55
|
-
obj = klass.new
|
56
|
-
assert_nil obj.latlon
|
57
|
-
obj.latlon = 'POINT(1 2)'
|
58
|
-
assert_equal @factory.point(1.0, 2.0), obj.latlon
|
59
|
-
assert_equal 3785, obj.latlon.srid
|
60
|
-
end
|
61
|
-
|
62
|
-
def test_save_and_load_point
|
63
|
-
klass = populate_ar_class(:mercator_point)
|
64
|
-
obj = klass.new
|
65
|
-
obj.latlon = @factory.point(1.0, 2.0)
|
66
|
-
obj.save!
|
67
|
-
id = obj.id
|
68
|
-
obj2 = klass.find(id)
|
69
|
-
assert_equal @factory.point(1.0, 2.0), obj2.latlon
|
70
|
-
assert_equal 3785, obj2.latlon.srid
|
71
|
-
assert_equal true, ::RGeo::Geos.is_geos?(obj2.latlon)
|
72
|
-
end
|
73
|
-
|
74
|
-
def test_save_and_load_geographic_point
|
75
|
-
klass = populate_ar_class(:latlon_point_geographic)
|
76
|
-
obj = klass.new
|
77
|
-
obj.latlon = @factory.point(1.0, 2.0)
|
78
|
-
obj.save!
|
79
|
-
id = obj.id
|
80
|
-
obj2 = klass.find(id)
|
81
|
-
assert_equal @geographic_factory.point(1.0, 2.0), obj2.latlon
|
82
|
-
assert_equal 4326, obj2.latlon.srid
|
83
|
-
assert_equal false, ::RGeo::Geos.is_geos?(obj2.latlon)
|
84
|
-
end
|
85
|
-
|
86
|
-
def test_save_and_load_point_from_wkt
|
87
|
-
klass = populate_ar_class(:mercator_point)
|
88
|
-
obj = klass.new
|
89
|
-
obj.latlon = 'POINT(1 2)'
|
90
|
-
obj.save!
|
91
|
-
id = obj.id
|
92
|
-
obj2 = klass.find(id)
|
93
|
-
assert_equal @factory.point(1.0, 2.0), obj2.latlon
|
94
|
-
assert_equal 3785, obj2.latlon.srid
|
95
|
-
end
|
96
|
-
|
97
|
-
def test_set_point_bad_wkt
|
98
|
-
klass = populate_ar_class(:mercator_point)
|
99
|
-
obj = klass.create(:latlon => 'POINT (x)')
|
100
|
-
assert_nil obj.latlon
|
101
|
-
end
|
102
|
-
|
103
|
-
def test_set_point_wkt_wrong_type
|
104
|
-
klass = populate_ar_class(:mercator_point)
|
105
|
-
assert_raises(::ActiveRecord::StatementInvalid) do
|
106
|
-
klass.create(:latlon => 'LINESTRING(1 2, 3 4, 5 6)')
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def test_custom_factory
|
111
|
-
klass = create_ar_class
|
112
|
-
klass.connection.create_table(:spatial_test) do |t|
|
113
|
-
t.point(:latlon, :srid => 4326)
|
114
|
-
end
|
115
|
-
factory = ::RGeo::Geographic.simple_mercator_factory
|
116
|
-
klass.class_eval do
|
117
|
-
set_rgeo_factory_for_column(:latlon, factory)
|
118
|
-
end
|
119
|
-
rec_ = klass.new
|
120
|
-
rec_.latlon = 'POINT(-122 47)'
|
121
|
-
assert_equal factory, rec_.latlon.factory
|
122
|
-
rec_.save!
|
123
|
-
assert_equal factory, rec_.latlon.factory
|
124
|
-
rec2_ = klass.find(rec_.id)
|
125
|
-
assert_equal factory, rec2_.latlon.factory
|
126
|
-
end
|
127
|
-
|
128
|
-
def test_readme_example
|
129
|
-
klass = create_ar_class
|
130
|
-
klass.connection.create_table(:spatial_test) do |t_|
|
131
|
-
t_.column(:shape, :geometry)
|
132
|
-
t_.line_string(:path, :srid => 3785)
|
133
|
-
t_.point(:latlon, :geographic => true)
|
134
|
-
end
|
135
|
-
klass.connection.change_table(:spatial_test) do |t_|
|
136
|
-
t_.index(:latlon, :spatial => true)
|
137
|
-
end
|
138
|
-
klass.class_eval do
|
139
|
-
self.rgeo_factory_generator = ::RGeo::Geos.method(:factory)
|
140
|
-
set_rgeo_factory_for_column(:latlon, ::RGeo::Geographic.spherical_factory)
|
141
|
-
end
|
142
|
-
rec_ = klass.new
|
143
|
-
rec_.latlon = 'POINT(-122 47)'
|
144
|
-
loc_ = rec_.latlon
|
145
|
-
assert_equal 47, loc_.latitude
|
146
|
-
rec_.shape = loc_
|
147
|
-
assert_equal true, ::RGeo::Geos.is_geos?(rec_.shape)
|
148
|
-
end
|
149
|
-
|
150
|
-
# no_constraints no longer supported in PostGIS 2.0
|
151
|
-
def _test_save_and_load_no_constraints
|
152
|
-
klass = populate_ar_class(:no_constraints)
|
153
|
-
factory1_ = ::RGeo::Cartesian.preferred_factory(:srid => 3785)
|
154
|
-
factory2_ = ::RGeo::Cartesian.preferred_factory(:srid => 2000)
|
155
|
-
obj = klass.new
|
156
|
-
obj.geo = factory1_.point(1.0, 2.0)
|
157
|
-
obj.save!
|
158
|
-
id = obj.id
|
159
|
-
obj2 = klass.find(id)
|
160
|
-
assert_equal factory1_.point(1.0, 2.0), obj2.geo
|
161
|
-
assert_equal 3785, obj2.geo.srid
|
162
|
-
obj2.geo = factory2_.point(3.0, 4.0)
|
163
|
-
obj2.save!
|
164
|
-
obj3 = klass.find(id)
|
165
|
-
assert_equal factory2_.point(3.0, 4.0), obj3.geo
|
166
|
-
assert_equal 2000, obj3.geo.srid
|
167
|
-
end
|
168
|
-
|
169
|
-
def test_point_to_json
|
170
|
-
klass = populate_ar_class(:mercator_point)
|
171
|
-
obj = klass.new
|
172
|
-
assert_match(/"latlon":null/, obj.to_json)
|
173
|
-
obj.latlon = @factory.point(1.0, 2.0)
|
174
|
-
assert_match(/"latlon":"POINT\s\(1\.0\s2\.0\)"/, obj.to_json)
|
175
|
-
end
|
176
|
-
|
177
|
-
def test_custom_column
|
178
|
-
klass = populate_ar_class(:mercator_point)
|
179
|
-
rec = klass.new
|
180
|
-
rec.latlon = 'POINT(0 0)'
|
181
|
-
rec.save
|
182
|
-
refute_nil klass.select("CURRENT_TIMESTAMP as ts").first.ts
|
183
|
-
end
|
184
|
-
|
185
|
-
end
|
3
|
+
class BasicTest < ActiveSupport::TestCase # :nodoc:
|
4
|
+
DATABASE_CONFIG_PATH = ::File.dirname(__FILE__)+'/database.yml'
|
5
|
+
OVERRIDE_DATABASE_CONFIG_PATH = ::File.dirname(__FILE__)+'/database_local.yml'
|
6
|
+
|
7
|
+
include RGeo::ActiveRecord::AdapterTestHelper
|
8
|
+
|
9
|
+
define_test_methods do
|
10
|
+
|
11
|
+
def populate_ar_class(content)
|
12
|
+
klass = create_ar_class
|
13
|
+
case content
|
14
|
+
when :mercator_point
|
15
|
+
klass.connection.create_table(:spatial_test) do |t_|
|
16
|
+
t_.column 'latlon', :point, :srid => 3785
|
17
|
+
end
|
18
|
+
when :latlon_point_geographic
|
19
|
+
klass.connection.create_table(:spatial_test) do |t_|
|
20
|
+
t_.column 'latlon', :point, :srid => 4326, :geographic => true
|
21
|
+
end
|
22
|
+
when :no_constraints
|
23
|
+
klass.connection.create_table(:spatial_test) do |t_|
|
24
|
+
t_.column 'geo', :geometry, :no_constraints => true
|
186
25
|
end
|
187
26
|
end
|
27
|
+
klass
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_version
|
31
|
+
refute_nil ::ActiveRecord::ConnectionAdapters::PostGISAdapter::VERSION
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_postgis_available
|
35
|
+
connection = create_ar_class.connection
|
36
|
+
assert_equal 'PostGIS', connection.adapter_name
|
37
|
+
refute_nil connection.postgis_lib_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_set_and_get_point
|
41
|
+
klass = populate_ar_class(:mercator_point)
|
42
|
+
obj = klass.new
|
43
|
+
assert_nil obj.latlon
|
44
|
+
obj.latlon = @factory.point(1.0, 2.0)
|
45
|
+
assert_equal @factory.point(1.0, 2.0), obj.latlon
|
46
|
+
assert_equal 3785, obj.latlon.srid
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_set_and_get_point_from_wkt
|
50
|
+
klass = populate_ar_class(:mercator_point)
|
51
|
+
obj = klass.new
|
52
|
+
assert_nil obj.latlon
|
53
|
+
obj.latlon = 'POINT(1 2)'
|
54
|
+
assert_equal @factory.point(1.0, 2.0), obj.latlon
|
55
|
+
assert_equal 3785, obj.latlon.srid
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_save_and_load_point
|
59
|
+
klass = populate_ar_class(:mercator_point)
|
60
|
+
obj = klass.new
|
61
|
+
obj.latlon = @factory.point(1.0, 2.0)
|
62
|
+
obj.save!
|
63
|
+
id = obj.id
|
64
|
+
obj2 = klass.find(id)
|
65
|
+
assert_equal @factory.point(1.0, 2.0), obj2.latlon
|
66
|
+
assert_equal 3785, obj2.latlon.srid
|
67
|
+
assert_equal true, ::RGeo::Geos.is_geos?(obj2.latlon)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_save_and_load_geographic_point
|
71
|
+
klass = populate_ar_class(:latlon_point_geographic)
|
72
|
+
obj = klass.new
|
73
|
+
obj.latlon = @factory.point(1.0, 2.0)
|
74
|
+
obj.save!
|
75
|
+
id = obj.id
|
76
|
+
obj2 = klass.find(id)
|
77
|
+
assert_equal @geographic_factory.point(1.0, 2.0), obj2.latlon
|
78
|
+
assert_equal 4326, obj2.latlon.srid
|
79
|
+
assert_equal false, ::RGeo::Geos.is_geos?(obj2.latlon)
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_save_and_load_point_from_wkt
|
83
|
+
klass = populate_ar_class(:mercator_point)
|
84
|
+
obj = klass.new
|
85
|
+
obj.latlon = 'POINT(1 2)'
|
86
|
+
obj.save!
|
87
|
+
id = obj.id
|
88
|
+
obj2 = klass.find(id)
|
89
|
+
assert_equal @factory.point(1.0, 2.0), obj2.latlon
|
90
|
+
assert_equal 3785, obj2.latlon.srid
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_set_point_bad_wkt
|
94
|
+
klass = populate_ar_class(:mercator_point)
|
95
|
+
obj = klass.create(:latlon => 'POINT (x)')
|
96
|
+
assert_nil obj.latlon
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_set_point_wkt_wrong_type
|
100
|
+
klass = populate_ar_class(:mercator_point)
|
101
|
+
assert_raises(::ActiveRecord::StatementInvalid) do
|
102
|
+
klass.create(:latlon => 'LINESTRING(1 2, 3 4, 5 6)')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_custom_factory
|
107
|
+
klass = create_ar_class
|
108
|
+
klass.connection.create_table(:spatial_test) do |t|
|
109
|
+
t.point(:latlon, :srid => 4326)
|
110
|
+
end
|
111
|
+
factory = ::RGeo::Geographic.simple_mercator_factory
|
112
|
+
klass.class_eval do
|
113
|
+
set_rgeo_factory_for_column(:latlon, factory)
|
114
|
+
end
|
115
|
+
rec_ = klass.new
|
116
|
+
rec_.latlon = 'POINT(-122 47)'
|
117
|
+
assert_equal factory, rec_.latlon.factory
|
118
|
+
rec_.save!
|
119
|
+
assert_equal factory, rec_.latlon.factory
|
120
|
+
rec2_ = klass.find(rec_.id)
|
121
|
+
assert_equal factory, rec2_.latlon.factory
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_readme_example
|
125
|
+
klass = create_ar_class
|
126
|
+
klass.connection.create_table(:spatial_test) do |t_|
|
127
|
+
t_.column(:shape, :geometry)
|
128
|
+
t_.line_string(:path, :srid => 3785)
|
129
|
+
t_.point(:latlon, :geographic => true)
|
130
|
+
end
|
131
|
+
klass.connection.change_table(:spatial_test) do |t_|
|
132
|
+
t_.index(:latlon, :spatial => true)
|
133
|
+
end
|
134
|
+
klass.class_eval do
|
135
|
+
self.rgeo_factory_generator = ::RGeo::Geos.method(:factory)
|
136
|
+
set_rgeo_factory_for_column(:latlon, ::RGeo::Geographic.spherical_factory)
|
137
|
+
end
|
138
|
+
rec_ = klass.new
|
139
|
+
rec_.latlon = 'POINT(-122 47)'
|
140
|
+
loc_ = rec_.latlon
|
141
|
+
assert_equal 47, loc_.latitude
|
142
|
+
rec_.shape = loc_
|
143
|
+
assert_equal true, ::RGeo::Geos.is_geos?(rec_.shape)
|
144
|
+
end
|
145
|
+
|
146
|
+
# no_constraints no longer supported in PostGIS 2.0
|
147
|
+
def _test_save_and_load_no_constraints
|
148
|
+
klass = populate_ar_class(:no_constraints)
|
149
|
+
factory1_ = ::RGeo::Cartesian.preferred_factory(:srid => 3785)
|
150
|
+
factory2_ = ::RGeo::Cartesian.preferred_factory(:srid => 2000)
|
151
|
+
obj = klass.new
|
152
|
+
obj.geo = factory1_.point(1.0, 2.0)
|
153
|
+
obj.save!
|
154
|
+
id = obj.id
|
155
|
+
obj2 = klass.find(id)
|
156
|
+
assert_equal factory1_.point(1.0, 2.0), obj2.geo
|
157
|
+
assert_equal 3785, obj2.geo.srid
|
158
|
+
obj2.geo = factory2_.point(3.0, 4.0)
|
159
|
+
obj2.save!
|
160
|
+
obj3 = klass.find(id)
|
161
|
+
assert_equal factory2_.point(3.0, 4.0), obj3.geo
|
162
|
+
assert_equal 2000, obj3.geo.srid
|
188
163
|
end
|
164
|
+
|
165
|
+
def test_point_to_json
|
166
|
+
klass = populate_ar_class(:mercator_point)
|
167
|
+
obj = klass.new
|
168
|
+
assert_match(/"latlon":null/, obj.to_json)
|
169
|
+
obj.latlon = @factory.point(1.0, 2.0)
|
170
|
+
assert_match(/"latlon":"POINT\s\(1\.0\s2\.0\)"/, obj.to_json)
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_custom_column
|
174
|
+
klass = populate_ar_class(:mercator_point)
|
175
|
+
rec = klass.new
|
176
|
+
rec.latlon = 'POINT(0 0)'
|
177
|
+
rec.save
|
178
|
+
refute_nil klass.select("CURRENT_TIMESTAMP as ts").first.ts
|
179
|
+
end
|
180
|
+
|
189
181
|
end
|
190
182
|
end
|