activerecord-postgis-adapter 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|