activerecord-postgis 0.3.1 → 0.5.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/activerecord-postgis.gemspec +1 -1
- data/lib/active_record/connection_adapters/postgis/column_methods.rb +1 -0
- data/lib/active_record/connection_adapters/postgis/quoting.rb +9 -7
- data/lib/active_record/connection_adapters/postgis/schema_statements.rb +1 -0
- data/lib/active_record/connection_adapters/postgis/spatial_column_type.rb +9 -4
- data/lib/active_record/connection_adapters/postgis/spatial_queries.rb +96 -0
- data/lib/active_record/connection_adapters/postgis/version.rb +1 -1
- data/lib/active_record/connection_adapters/postgis.rb +1 -0
- data/lib/arel/visitors/postgis.rb +27 -7
- metadata +6 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b80f70c84d88643edef39e5d702779a4248b05c03ed692c09139bad00f7f5009
|
|
4
|
+
data.tar.gz: 9f923717999ac80231119e353356f8f9570c04e17ef560e84aa0656132ec0618
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aff8a1b78d4b16f498c013652b5fd0d1b9b268fe9292197e7d799e12c8cfa562be6f6ba9a118fd3bab8cef19f028439db1befa6da02528e81c7aede7669560d6
|
|
7
|
+
data.tar.gz: 8cb2c7bfe70dfdab95a8c8d535f5b7397be7b03978808b01a3169979cc6c417eae1f4a9c8e24043b5196aa5bfb678bd50c1778393ed40429f10b58d82f3666fd
|
|
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
spec.files = Dir.glob('{lib}/**/*') + [ gemspec, 'LICENSE.txt', 'README.md' ]
|
|
23
23
|
spec.require_paths = [ 'lib' ]
|
|
24
24
|
|
|
25
|
-
spec.add_dependency 'activerecord', '>= 8.0', '< 8.
|
|
25
|
+
spec.add_dependency 'activerecord', '>= 8.1.0', '< 8.2'
|
|
26
26
|
spec.add_dependency 'pg'
|
|
27
27
|
spec.add_dependency 'rgeo-activerecord', '>= 8.0'
|
|
28
28
|
end
|
|
@@ -18,13 +18,15 @@ module ActiveRecord
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def type_cast(value)
|
|
21
|
-
if
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
if RGeo::Feature::Geometry.check_type(value)
|
|
22
|
+
# Use EWKB format to preserve SRID information
|
|
23
|
+
RGeo::WKRep::WKBGenerator.new(
|
|
24
|
+
hex_format: true,
|
|
25
|
+
type_format: :ewkb,
|
|
26
|
+
emit_ewkb_srid: true
|
|
27
|
+
).generate(value)
|
|
28
|
+
elsif value.is_a?(RGeo::Cartesian::BoundingBox)
|
|
29
|
+
value.to_s
|
|
28
30
|
else
|
|
29
31
|
super
|
|
30
32
|
end
|
|
@@ -120,10 +120,15 @@ module ActiveRecord
|
|
|
120
120
|
return base_type if @type == "geography"
|
|
121
121
|
|
|
122
122
|
type_with_dimensions = build_type_with_dimensions
|
|
123
|
-
# Include SRID if specified and not the default for the type
|
|
124
|
-
# Geography
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
# Include SRID if specified and not the default for the column type
|
|
124
|
+
# Geography columns: only include SRID if it's not the default 4326
|
|
125
|
+
# Geometry columns: always include SRID when specified and not 0
|
|
126
|
+
if @geography
|
|
127
|
+
should_include_srid = @srid && @srid != 4326
|
|
128
|
+
else
|
|
129
|
+
# For geometry columns, always include SRID when explicitly specified and not 0
|
|
130
|
+
should_include_srid = @srid && @srid != 0
|
|
131
|
+
end
|
|
127
132
|
|
|
128
133
|
if should_include_srid
|
|
129
134
|
"#{base_type}(#{type_with_dimensions},#{@srid})"
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module ConnectionAdapters
|
|
5
|
+
module PostGIS
|
|
6
|
+
module SpatialQueries
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
class_methods do
|
|
10
|
+
# Safe wrapper for ST_Distance queries
|
|
11
|
+
# Usage: Model.where_st_distance(:column, lon, lat, '<', distance)
|
|
12
|
+
# For geographic calculations (meters), cast to geography
|
|
13
|
+
def where_st_distance(column, lon, lat, operator, distance, srid: 4326, geographic: false)
|
|
14
|
+
if geographic
|
|
15
|
+
where("ST_Distance(#{column}::geography, ST_SetSRID(ST_MakePoint(?, ?), ?)::geography) #{operator} ?", lon, lat, srid, distance)
|
|
16
|
+
else
|
|
17
|
+
where("ST_Distance(#{column}, ST_SetSRID(ST_MakePoint(?, ?), ?)) #{operator} ?", lon, lat, srid, distance)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Safe wrapper for ST_DWithin queries
|
|
22
|
+
# Usage: Model.where_st_dwithin(:column, lon, lat, distance)
|
|
23
|
+
# For geographic calculations (meters), cast to geography
|
|
24
|
+
def where_st_dwithin(column, lon, lat, distance, srid: 4326, geographic: false)
|
|
25
|
+
if geographic
|
|
26
|
+
where("ST_DWithin(#{column}::geography, ST_SetSRID(ST_MakePoint(?, ?), ?)::geography, ?)", lon, lat, srid, distance)
|
|
27
|
+
else
|
|
28
|
+
where("ST_DWithin(#{column}, ST_SetSRID(ST_MakePoint(?, ?), ?), ?)", lon, lat, srid, distance)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Safe wrapper for ST_Contains with point
|
|
33
|
+
# Usage: Model.where_st_contains(:column, lon, lat)
|
|
34
|
+
def where_st_contains(column, lon, lat, srid: 4326)
|
|
35
|
+
where("ST_Contains(#{column}, ST_SetSRID(ST_MakePoint(?, ?), ?))", lon, lat, srid)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Safe wrapper for ST_Within with point
|
|
39
|
+
# Usage: Model.where_st_within_point(:column, lon, lat)
|
|
40
|
+
def where_st_within_point(column, lon, lat, srid: 4326)
|
|
41
|
+
where("ST_Within(ST_SetSRID(ST_MakePoint(?, ?), ?), #{column})", lon, lat, srid)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Safe wrapper for ST_Intersects with WKT geometry
|
|
45
|
+
# Usage: Model.where_st_intersects(:column, wkt_string)
|
|
46
|
+
def where_st_intersects(column, wkt, srid: 4326)
|
|
47
|
+
where("ST_Intersects(#{column}, ST_GeomFromText(?, ?))", wkt, srid)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Generic safe wrapper for any PostGIS function with a point parameter
|
|
51
|
+
# Usage: Model.where_st_function('ST_Distance', :column, lon, lat, '<', value)
|
|
52
|
+
def where_st_function(function, column, lon, lat, operator = nil, value = nil, srid: 4326)
|
|
53
|
+
if operator && value
|
|
54
|
+
where("#{function}(#{column}, ST_SetSRID(ST_MakePoint(?, ?), ?)) #{operator} ?", lon, lat, srid, value)
|
|
55
|
+
else
|
|
56
|
+
where("#{function}(#{column}, ST_SetSRID(ST_MakePoint(?, ?), ?))", lon, lat, srid)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Module to include in models for instance methods
|
|
63
|
+
module SpatialScopes
|
|
64
|
+
extend ActiveSupport::Concern
|
|
65
|
+
|
|
66
|
+
included do
|
|
67
|
+
# Define commonly used spatial scopes
|
|
68
|
+
scope :within_distance, ->(column, lon, lat, distance, srid: 4326, geographic: false) {
|
|
69
|
+
where_st_distance(column, lon, lat, "<", distance, srid: srid, geographic: geographic)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
scope :beyond_distance, ->(column, lon, lat, distance, srid: 4326, geographic: false) {
|
|
73
|
+
where_st_distance(column, lon, lat, ">", distance, srid: srid, geographic: geographic)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
scope :near, ->(column, lon, lat, distance, srid: 4326, geographic: false) {
|
|
77
|
+
where_st_dwithin(column, lon, lat, distance, srid: srid, geographic: geographic)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
scope :containing_point, ->(column, lon, lat, srid: 4326) {
|
|
81
|
+
where_st_contains(column, lon, lat, srid: srid)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
scope :intersecting, ->(column, wkt, srid: 4326) {
|
|
85
|
+
where_st_intersects(column, wkt, srid: srid)
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Automatically include in ActiveRecord::Base
|
|
94
|
+
ActiveSupport.on_load(:active_record) do
|
|
95
|
+
ActiveRecord::Base.include(ActiveRecord::ConnectionAdapters::PostGIS::SpatialQueries)
|
|
96
|
+
end
|
|
@@ -19,6 +19,7 @@ require_relative "postgis/spatial_column_type"
|
|
|
19
19
|
require_relative "postgis/adapter_extensions"
|
|
20
20
|
require_relative "postgis/column_extensions"
|
|
21
21
|
require_relative "postgis/quoting"
|
|
22
|
+
require_relative "postgis/spatial_queries"
|
|
22
23
|
|
|
23
24
|
module ActiveRecord
|
|
24
25
|
module ConnectionAdapters
|
|
@@ -19,7 +19,7 @@ module Arel
|
|
|
19
19
|
class SpatialIntersects < SpatialNode; end
|
|
20
20
|
class SpatialDWithin < SpatialNode
|
|
21
21
|
attr_reader :distance
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
def initialize(left, right, distance)
|
|
24
24
|
super(left, right)
|
|
25
25
|
@distance = distance
|
|
@@ -36,7 +36,7 @@ module Arel
|
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
class SpatialArea < Unary; end
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
# K-Nearest Neighbor distance operator
|
|
41
41
|
class SpatialDistanceOperator < Binary
|
|
42
42
|
def initialize(left, right)
|
|
@@ -83,11 +83,11 @@ module Arel
|
|
|
83
83
|
def st_area
|
|
84
84
|
SpatialArea.new(self)
|
|
85
85
|
end
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
def distance_operator(other)
|
|
88
88
|
SpatialDistanceOperator.new(self, other)
|
|
89
89
|
end
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
alias :'<->' :distance_operator
|
|
92
92
|
end
|
|
93
93
|
end
|
|
@@ -129,11 +129,11 @@ module Arel
|
|
|
129
129
|
def st_area
|
|
130
130
|
Arel::Nodes::SpatialArea.new(self)
|
|
131
131
|
end
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
def distance_operator(other)
|
|
134
134
|
Arel::Nodes::SpatialDistanceOperator.new(self, other)
|
|
135
135
|
end
|
|
136
|
-
|
|
136
|
+
|
|
137
137
|
alias :'<->' :distance_operator
|
|
138
138
|
end
|
|
139
139
|
end
|
|
@@ -143,6 +143,26 @@ module Arel
|
|
|
143
143
|
Arel::Nodes::SpatialValue.new(value)
|
|
144
144
|
end
|
|
145
145
|
|
|
146
|
+
# Add Arel.st_make_point() method that properly handles floats for Rails 8.1
|
|
147
|
+
def self.st_make_point(x, y, srid = nil)
|
|
148
|
+
# Wrap floats in SqlLiteral nodes to avoid Rails 8.1 Arel strictness
|
|
149
|
+
x_node = x.is_a?(Numeric) ? Arel::Nodes::SqlLiteral.new(x.to_s) : x
|
|
150
|
+
y_node = y.is_a?(Numeric) ? Arel::Nodes::SqlLiteral.new(y.to_s) : y
|
|
151
|
+
|
|
152
|
+
if srid
|
|
153
|
+
srid_node = srid.is_a?(Numeric) ? Arel::Nodes::SqlLiteral.new(srid.to_s) : srid
|
|
154
|
+
Arel::Nodes::NamedFunction.new(
|
|
155
|
+
"ST_SetSRID",
|
|
156
|
+
[
|
|
157
|
+
Arel::Nodes::NamedFunction.new("ST_MakePoint", [ x_node, y_node ]),
|
|
158
|
+
srid_node
|
|
159
|
+
]
|
|
160
|
+
)
|
|
161
|
+
else
|
|
162
|
+
Arel::Nodes::NamedFunction.new("ST_MakePoint", [ x_node, y_node ])
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
146
166
|
module Visitors
|
|
147
167
|
class PostGIS < PostgreSQL
|
|
148
168
|
include RGeo::ActiveRecord::SpatialToSql
|
|
@@ -230,7 +250,7 @@ module Arel
|
|
|
230
250
|
visit(node.expr, collector)
|
|
231
251
|
collector << ")"
|
|
232
252
|
end
|
|
233
|
-
|
|
253
|
+
|
|
234
254
|
def visit_Arel_Nodes_SpatialDistanceOperator(node, collector)
|
|
235
255
|
visit(node.left, collector)
|
|
236
256
|
collector << " <-> "
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord-postgis
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Abdelkader Boudih
|
|
@@ -15,20 +15,20 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version:
|
|
18
|
+
version: 8.1.0
|
|
19
19
|
- - "<"
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: '8.
|
|
21
|
+
version: '8.2'
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
25
|
requirements:
|
|
26
26
|
- - ">="
|
|
27
27
|
- !ruby/object:Gem::Version
|
|
28
|
-
version:
|
|
28
|
+
version: 8.1.0
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
|
-
version: '8.
|
|
31
|
+
version: '8.2'
|
|
32
32
|
- !ruby/object:Gem::Dependency
|
|
33
33
|
name: pg
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -79,6 +79,7 @@ files:
|
|
|
79
79
|
- lib/active_record/connection_adapters/postgis/schema_statements.rb
|
|
80
80
|
- lib/active_record/connection_adapters/postgis/spatial_column_methods.rb
|
|
81
81
|
- lib/active_record/connection_adapters/postgis/spatial_column_type.rb
|
|
82
|
+
- lib/active_record/connection_adapters/postgis/spatial_queries.rb
|
|
82
83
|
- lib/active_record/connection_adapters/postgis/table_definition.rb
|
|
83
84
|
- lib/active_record/connection_adapters/postgis/test_helpers.rb
|
|
84
85
|
- lib/active_record/connection_adapters/postgis/type/geography.rb
|