activerecord-spatial 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1670 -0
- data/Gemfile +12 -13
- data/Guardfile +7 -10
- data/MIT-LICENSE +1 -1
- data/README.rdoc +8 -19
- data/Rakefile +2 -1
- data/activerecord-spatial.gemspec +12 -13
- data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/adapter_extensions/active_record.rb +46 -0
- data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/adapter_extensions.rb +7 -38
- data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/postgis.rb +6 -7
- data/lib/activerecord-spatial/active_record/connection_adapters/postgresql/unknown_srid.rb +4 -5
- data/lib/activerecord-spatial/active_record/models/geography_column.rb +1 -2
- data/lib/activerecord-spatial/active_record/models/geometry_column.rb +1 -2
- data/lib/activerecord-spatial/active_record/models/spatial_column.rb +1 -2
- data/lib/activerecord-spatial/active_record/models/spatial_ref_sys.rb +5 -6
- data/lib/activerecord-spatial/active_record.rb +0 -1
- data/lib/activerecord-spatial/associations/active_record.rb +62 -120
- data/lib/activerecord-spatial/associations/base.rb +26 -75
- data/lib/activerecord-spatial/associations/preloader/spatial_association.rb +57 -0
- data/lib/activerecord-spatial/associations/reflection/spatial_reflection.rb +41 -0
- data/lib/activerecord-spatial/associations.rb +26 -4
- data/lib/activerecord-spatial/spatial_columns.rb +85 -94
- data/lib/activerecord-spatial/spatial_function.rb +62 -51
- data/lib/activerecord-spatial/spatial_scope_constants/postgis_2_0.rb +48 -0
- data/lib/activerecord-spatial/spatial_scope_constants/postgis_2_2.rb +46 -0
- data/lib/activerecord-spatial/spatial_scope_constants/postgis_legacy.rb +30 -0
- data/lib/activerecord-spatial/spatial_scope_constants.rb +10 -61
- data/lib/activerecord-spatial/spatial_scopes.rb +47 -49
- data/lib/activerecord-spatial/version.rb +1 -2
- data/lib/activerecord-spatial.rb +2 -6
- data/lib/tasks/test.rake +21 -19
- data/test/.rubocop.yml +35 -0
- data/test/accessors_geographies_tests.rb +19 -19
- data/test/accessors_geometries_tests.rb +19 -19
- data/test/adapter_tests.rb +1 -2
- data/test/associations_tests.rb +181 -203
- data/test/geography_column_tests.rb +2 -3
- data/test/geometry_column_tests.rb +1 -2
- data/test/models/bar.rb +2 -3
- data/test/models/blort.rb +1 -2
- data/test/models/foo.rb +2 -3
- data/test/models/foo3d.rb +2 -3
- data/test/models/foo_geography.rb +2 -3
- data/test/models/zortable.rb +2 -3
- data/test/spatial_function_tests.rb +12 -17
- data/test/spatial_scopes_geographies_tests.rb +17 -20
- data/test/spatial_scopes_tests.rb +84 -75
- data/test/test_helper.rb +66 -79
- metadata +16 -14
- data/lib/activerecord-spatial/associations/active_record_3.rb +0 -123
@@ -2,8 +2,8 @@
|
|
2
2
|
module ActiveRecordSpatial
|
3
3
|
class SpatialFunction
|
4
4
|
DEFAULT_OPTIONS = {
|
5
|
-
:
|
6
|
-
:
|
5
|
+
column: ActiveRecordSpatial.default_column_name,
|
6
|
+
use_index: true
|
7
7
|
}.freeze
|
8
8
|
|
9
9
|
def initialize(klass)
|
@@ -18,30 +18,32 @@ module ActiveRecordSpatial
|
|
18
18
|
options = default_options(args.extract_options!)
|
19
19
|
|
20
20
|
geom = options.fetch(:geom_arg, args.first)
|
21
|
-
args = Array.wrap(options.fetch(:args, args.from(1)))
|
21
|
+
args = Array.wrap(options.fetch(:args, args.from(1))).collect do |arg|
|
22
|
+
arel_quoted_value(arg)
|
23
|
+
end
|
22
24
|
|
23
|
-
column_name =
|
24
|
-
first_geom_arg =
|
25
|
+
column_name = column_name(options[:column])
|
26
|
+
first_geom_arg = wrap_column_or_geometry(
|
25
27
|
@klass.arel_table[column_name],
|
26
28
|
options[:column]
|
27
29
|
)
|
28
|
-
geom_args = [
|
30
|
+
geom_args = [first_geom_arg]
|
29
31
|
|
30
32
|
if geom.present?
|
31
33
|
column_type = @klass.spatial_column_by_name(column_name).spatial_type
|
32
34
|
column_srid = @klass.srid_for(column_name)
|
33
35
|
|
34
|
-
|
36
|
+
if !geom.is_a?(Hash)
|
35
37
|
geom_arg = read_geos(geom, column_srid)
|
36
38
|
geom_srid = read_geom_srid(geom_arg, column_type)
|
37
|
-
geom_args <<
|
39
|
+
geom_args << set_srid_or_transform(column_srid, geom_srid, geom_arg, column_type)
|
38
40
|
else
|
39
41
|
klass = if geom[:class]
|
40
42
|
geom[:class]
|
41
43
|
elsif geom[:class_name]
|
42
44
|
geom[:class_name].classify.constantize
|
43
45
|
else
|
44
|
-
raise ArgumentError
|
46
|
+
raise ArgumentError, 'Need either a :class or :class_name option to determine the class.'
|
45
47
|
end
|
46
48
|
|
47
49
|
if geom[:value]
|
@@ -49,35 +51,49 @@ module ActiveRecordSpatial
|
|
49
51
|
geom_srid = read_geom_srid(geom_arg, column_type)
|
50
52
|
else
|
51
53
|
geom_arg = geom
|
52
|
-
geom_srid = klass.srid_for(
|
54
|
+
geom_srid = klass.srid_for(column_name(geom[:column]))
|
53
55
|
end
|
54
56
|
|
55
|
-
transformed_geom =
|
56
|
-
geom_args <<
|
57
|
+
transformed_geom = set_srid_or_transform(column_srid, geom_srid, geom_arg, column_type)
|
58
|
+
geom_args << wrap_column_or_geometry(transformed_geom, geom)
|
57
59
|
end
|
58
60
|
end
|
59
61
|
|
60
|
-
if options[:invert] && geom_args.length > 1
|
61
|
-
geom_args.reverse!
|
62
|
-
end
|
62
|
+
geom_args.reverse! if options[:invert] && geom_args.length > 1
|
63
63
|
|
64
64
|
ret = Arel::Nodes::NamedFunction.new(
|
65
65
|
function_name(function, options[:use_index]),
|
66
66
|
geom_args + args
|
67
67
|
)
|
68
68
|
|
69
|
-
if options[:allow_null]
|
70
|
-
ret = ret.or(first_geom_arg.eq(nil))
|
71
|
-
end
|
69
|
+
ret = ret.or(first_geom_arg.eq(nil)) if options[:allow_null]
|
72
70
|
|
73
71
|
ret
|
74
72
|
end
|
75
73
|
|
76
|
-
|
74
|
+
class << self
|
75
|
+
def additional_ordering(*args)
|
76
|
+
options = args.extract_options!
|
77
|
+
|
78
|
+
desc = if args.first == :desc
|
79
|
+
true
|
80
|
+
else
|
81
|
+
options[:desc]
|
82
|
+
end
|
83
|
+
|
84
|
+
''.tap do |ret|
|
85
|
+
ret << ' DESC' if desc
|
86
|
+
ret << " NULLS #{options[:nulls].to_s.upcase}" if options[:nulls]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
77
93
|
def set_srid_or_transform(column_srid, geom_srid, geom, type)
|
78
94
|
geom_param = case geom
|
79
95
|
when Geos::Geometry
|
80
|
-
Arel.sql("#{@klass.connection.quote(geom.to_ewkb)}
|
96
|
+
Arel.sql("#{@klass.connection.quote(geom.to_ewkb)}::geometry")
|
81
97
|
when Hash
|
82
98
|
table_name = if geom[:table_alias]
|
83
99
|
@klass.connection.quote_table_name(geom[:table_alias])
|
@@ -87,22 +103,22 @@ module ActiveRecordSpatial
|
|
87
103
|
geom[:class_name].classify.constantize.quoted_table_name
|
88
104
|
end
|
89
105
|
|
90
|
-
Arel.sql("#{table_name}.#{@klass.connection.quote_table_name(
|
106
|
+
Arel.sql("#{table_name}.#{@klass.connection.quote_table_name(column_name(geom[:column]))}")
|
91
107
|
else
|
92
|
-
raise ArgumentError
|
108
|
+
raise ArgumentError, 'Expected either a Geos::Geometry or a Hash.'
|
93
109
|
end
|
94
110
|
|
95
|
-
|
111
|
+
if column_srid != geom_srid
|
96
112
|
if column_srid == ActiveRecordSpatial::UNKNOWN_SRIDS[type] || geom_srid == ActiveRecordSpatial::UNKNOWN_SRIDS[type]
|
97
113
|
Arel::Nodes::NamedFunction.new(
|
98
114
|
function_name('SetSRID'),
|
99
|
-
[
|
115
|
+
[geom_param, column_srid]
|
100
116
|
)
|
101
117
|
|
102
118
|
else
|
103
119
|
Arel::Nodes::NamedFunction.new(
|
104
120
|
function_name('Transform'),
|
105
|
-
[
|
121
|
+
[geom_param, column_srid]
|
106
122
|
)
|
107
123
|
end
|
108
124
|
else
|
@@ -118,7 +134,7 @@ module ActiveRecordSpatial
|
|
118
134
|
end
|
119
135
|
|
120
136
|
def read_geom_srid(geos, column_type = :geometry)
|
121
|
-
if geos.srid
|
137
|
+
if geos.srid.zero? || geos.srid == -1
|
122
138
|
ActiveRecordSpatial::UNKNOWN_SRIDS[column_type]
|
123
139
|
else
|
124
140
|
geos.srid
|
@@ -128,16 +144,16 @@ module ActiveRecordSpatial
|
|
128
144
|
def default_options(*args)
|
129
145
|
options = args.extract_options!
|
130
146
|
|
131
|
-
if args.length
|
147
|
+
if args.length.positive?
|
132
148
|
desc = if args.first == :desc
|
133
149
|
true
|
134
150
|
else
|
135
151
|
options[:desc]
|
136
152
|
end
|
137
153
|
|
138
|
-
DEFAULT_OPTIONS.merge(
|
139
|
-
:
|
140
|
-
|
154
|
+
DEFAULT_OPTIONS.merge(
|
155
|
+
desc: desc
|
156
|
+
).merge(options || {})
|
141
157
|
else
|
142
158
|
DEFAULT_OPTIONS.merge(options || {})
|
143
159
|
end
|
@@ -156,47 +172,42 @@ module ActiveRecordSpatial
|
|
156
172
|
column_name_or_options[:name]
|
157
173
|
else
|
158
174
|
column_name_or_options
|
159
|
-
end
|
175
|
+
end
|
176
|
+
|
177
|
+
column_name || ActiveRecordSpatial.default_column_name
|
160
178
|
end
|
161
179
|
|
162
180
|
def wrap_column_or_geometry(column_name_or_geometry, options = nil)
|
163
181
|
if options.is_a?(Hash) && options[:wrapper]
|
164
182
|
wrapper, args = if options[:wrapper].is_a?(Hash)
|
165
|
-
[
|
183
|
+
[options[:wrapper].keys.first, Array.wrap(options[:wrapper].values.first)]
|
166
184
|
else
|
167
|
-
[
|
185
|
+
[options[:wrapper], []]
|
168
186
|
end
|
169
187
|
|
170
188
|
Arel::Nodes::NamedFunction.new(
|
171
189
|
function_name(wrapper),
|
172
|
-
[
|
190
|
+
[column_name_or_geometry, *args.collect { |arg| arel_quoted_value(arg) }]
|
173
191
|
)
|
174
192
|
else
|
175
193
|
column_name_or_geometry
|
176
194
|
end
|
177
195
|
end
|
178
196
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
desc = if args.first == :desc
|
184
|
-
true
|
197
|
+
def arel_nodes_quoted?
|
198
|
+
if defined?(@arel_nodes_quoted)
|
199
|
+
@arel_nodes_quoted
|
185
200
|
else
|
186
|
-
|
201
|
+
@arel_nodes_quoted = defined?(Arel::Nodes::Quoted)
|
187
202
|
end
|
203
|
+
end
|
188
204
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
if options[:nulls]
|
195
|
-
ret << " NULLS #{options[:nulls].to_s.upcase}"
|
196
|
-
end
|
205
|
+
def arel_quoted_value(value)
|
206
|
+
if arel_nodes_quoted?
|
207
|
+
Arel::Nodes::Quoted.new(value)
|
208
|
+
else
|
209
|
+
value
|
197
210
|
end
|
198
211
|
end
|
199
|
-
end
|
200
212
|
end
|
201
213
|
end
|
202
|
-
|
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
module ActiveRecordSpatial
|
3
|
+
module SpatialScopeConstants
|
4
|
+
ONE_ARGUMENT_MEASUREMENTS = %w{
|
5
|
+
3dlength_spheroid
|
6
|
+
length2d_spheroid
|
7
|
+
length_spheroid
|
8
|
+
}
|
9
|
+
|
10
|
+
ONE_ARGUMENT_MEASUREMENTS.concat(%w{
|
11
|
+
3dlength_spheroid
|
12
|
+
})
|
13
|
+
|
14
|
+
RELATIONSHIPS.concat(%w{
|
15
|
+
3dintersects
|
16
|
+
})
|
17
|
+
|
18
|
+
ZERO_ARGUMENT_MEASUREMENTS.concat(%w{
|
19
|
+
3dlength
|
20
|
+
3dperimeter
|
21
|
+
})
|
22
|
+
|
23
|
+
ONE_GEOMETRY_ARGUMENT_MEASUREMENTS.concat(%w{
|
24
|
+
3ddistance
|
25
|
+
3dmaxdistance
|
26
|
+
distance_sphere
|
27
|
+
})
|
28
|
+
|
29
|
+
ONE_GEOMETRY_ARGUMENT_AND_ONE_ARGUMENT_RELATIONSHIPS.concat(%w{
|
30
|
+
3ddwithin
|
31
|
+
3ddfullywithin
|
32
|
+
})
|
33
|
+
|
34
|
+
COMPATIBILITY_FUNCTION_ALIASES.merge!(
|
35
|
+
'order_by_st_length3d' => 'order_by_st_3dlength',
|
36
|
+
'order_by_st_perimeter3d' => 'order_by_st_3dperimeter',
|
37
|
+
'order_by_st_length3d_spheroid' => 'order_by_st_3dlength_spheroid',
|
38
|
+
'order_by_st_distancesphere' => 'order_by_st_distance_sphere'
|
39
|
+
)
|
40
|
+
|
41
|
+
FUNCTION_ALIASES.merge!(
|
42
|
+
'st_3d_dwithin' => 'st_3ddwithin',
|
43
|
+
'st_3d_dfully_within' => 'st_3ddfullywithin',
|
44
|
+
'order_by_st_3d_distance' => 'order_by_st_3ddistance',
|
45
|
+
'order_by_st_3d_max_distance' => 'order_by_st_3dmaxdistance'
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
module ActiveRecordSpatial
|
3
|
+
module SpatialScopeConstants
|
4
|
+
ONE_ARGUMENT_MEASUREMENTS = %w{
|
5
|
+
lengthspheroid
|
6
|
+
}
|
7
|
+
|
8
|
+
RELATIONSHIPS.concat(%w{
|
9
|
+
3dintersects
|
10
|
+
})
|
11
|
+
|
12
|
+
ZERO_ARGUMENT_MEASUREMENTS.concat(%w{
|
13
|
+
3dlength
|
14
|
+
3dperimeter
|
15
|
+
})
|
16
|
+
|
17
|
+
ONE_GEOMETRY_ARGUMENT_MEASUREMENTS.concat(%w{
|
18
|
+
3ddistance
|
19
|
+
3dmaxdistance
|
20
|
+
distancesphere
|
21
|
+
})
|
22
|
+
|
23
|
+
ONE_GEOMETRY_ARGUMENT_AND_ONE_ARGUMENT_RELATIONSHIPS.concat(%w{
|
24
|
+
3ddwithin
|
25
|
+
3ddfullywithin
|
26
|
+
})
|
27
|
+
|
28
|
+
COMPATIBILITY_FUNCTION_ALIASES.merge!(
|
29
|
+
'order_by_st_length3d' => 'order_by_st_3dlength',
|
30
|
+
'order_by_st_perimeter3d' => 'order_by_st_3dperimeter',
|
31
|
+
'order_by_st_3dlength_spheroid' => 'order_by_st_lengthspheroid',
|
32
|
+
'order_by_st_length3d_spheroid' => 'order_by_st_lengthspheroid',
|
33
|
+
'order_by_st_2dlength_spheroid' => 'order_by_st_lengthspheroid',
|
34
|
+
'order_by_st_length2d_spheroid' => 'order_by_st_lengthspheroid',
|
35
|
+
'order_by_st_length_spheroid' => 'order_by_st_lengthspheroid',
|
36
|
+
'order_by_st_distance_sphere' => 'order_by_st_distancesphere'
|
37
|
+
)
|
38
|
+
|
39
|
+
FUNCTION_ALIASES.merge!(
|
40
|
+
'st_3d_dwithin' => 'st_3ddwithin',
|
41
|
+
'st_3d_dfully_within' => 'st_3ddfullywithin',
|
42
|
+
'order_by_st_3d_distance' => 'order_by_st_3ddistance',
|
43
|
+
'order_by_st_3d_max_distance' => 'order_by_st_3dmaxdistance'
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module ActiveRecordSpatial
|
3
|
+
module SpatialScopeConstants
|
4
|
+
ONE_ARGUMENT_MEASUREMENTS = %w{
|
5
|
+
3dlength_spheroid
|
6
|
+
length2d_spheroid
|
7
|
+
length_spheroid
|
8
|
+
}
|
9
|
+
|
10
|
+
ONE_GEOMETRY_ARGUMENT_MEASUREMENTS.concat(%w{
|
11
|
+
distance_sphere
|
12
|
+
})
|
13
|
+
|
14
|
+
ZERO_ARGUMENT_MEASUREMENTS.concat(%w{
|
15
|
+
length3d
|
16
|
+
perimeter3d
|
17
|
+
})
|
18
|
+
|
19
|
+
ONE_ARGUMENT_MEASUREMENTS.concat(%w{
|
20
|
+
length3d_spheroid
|
21
|
+
})
|
22
|
+
|
23
|
+
COMPATIBILITY_FUNCTION_ALIASES.merge!(
|
24
|
+
'order_by_st_3dlength' => 'order_by_st_length3d',
|
25
|
+
'order_by_st_3dperimeter' => 'order_by_st_perimeter3d',
|
26
|
+
'order_by_st_3dlength_spheroid' => 'order_by_st_length3d_spheroid',
|
27
|
+
'order_by_st_distancesphere' => 'order_by_st_distance_sphere'
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
@@ -33,7 +33,7 @@ module ActiveRecordSpatial
|
|
33
33
|
|
34
34
|
ONE_GEOMETRY_ARGUMENT_MEASUREMENTS = %w{
|
35
35
|
distance
|
36
|
-
|
36
|
+
distancesphere
|
37
37
|
maxdistance
|
38
38
|
}
|
39
39
|
|
@@ -42,73 +42,22 @@ module ActiveRecordSpatial
|
|
42
42
|
dfullywithin
|
43
43
|
}
|
44
44
|
|
45
|
-
ONE_ARGUMENT_MEASUREMENTS = %w{
|
46
|
-
length2d_spheroid
|
47
|
-
length_spheroid
|
48
|
-
}
|
49
|
-
|
50
|
-
# Some functions were renamed in PostGIS 2.0.
|
51
|
-
if ActiveRecordSpatial::POSTGIS[:lib] >= '2.0'
|
52
|
-
RELATIONSHIPS.concat(%w{
|
53
|
-
3dintersects
|
54
|
-
})
|
55
|
-
|
56
|
-
ZERO_ARGUMENT_MEASUREMENTS.concat(%w{
|
57
|
-
3dlength
|
58
|
-
3dperimeter
|
59
|
-
})
|
60
|
-
|
61
|
-
ONE_ARGUMENT_MEASUREMENTS.concat(%w{
|
62
|
-
3dlength_spheroid
|
63
|
-
})
|
64
|
-
|
65
|
-
ONE_GEOMETRY_ARGUMENT_MEASUREMENTS.concat(%w{
|
66
|
-
3ddistance
|
67
|
-
3dmaxdistance
|
68
|
-
})
|
69
|
-
|
70
|
-
ONE_GEOMETRY_ARGUMENT_AND_ONE_ARGUMENT_RELATIONSHIPS.concat(%w{
|
71
|
-
3ddwithin
|
72
|
-
3ddfullywithin
|
73
|
-
})
|
74
|
-
else
|
75
|
-
ZERO_ARGUMENT_MEASUREMENTS.concat(%w{
|
76
|
-
length3d
|
77
|
-
perimeter3d
|
78
|
-
})
|
79
|
-
|
80
|
-
ONE_ARGUMENT_MEASUREMENTS.concat(%w{
|
81
|
-
length3d_spheroid
|
82
|
-
})
|
83
|
-
end
|
84
|
-
|
85
45
|
FUNCTION_ALIASES = {
|
86
46
|
'order_by_st_max_distance' => 'order_by_st_maxdistance',
|
87
47
|
'st_geometrytype' => 'st_geometry_type'
|
88
48
|
}
|
89
49
|
|
90
|
-
COMPATIBILITY_FUNCTION_ALIASES =
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
50
|
+
COMPATIBILITY_FUNCTION_ALIASES = {}
|
51
|
+
|
52
|
+
# Some functions were renamed or deprecated in PostGIS 2.2.
|
53
|
+
if ActiveRecordSpatial::POSTGIS[:lib] >= '2.2'
|
54
|
+
require 'activerecord-spatial/spatial_scope_constants/postgis_2_2'
|
55
|
+
elsif ActiveRecordSpatial::POSTGIS[:lib] >= '2.0'
|
56
|
+
require 'activerecord-spatial/spatial_scope_constants/postgis_2_0'
|
96
57
|
else
|
97
|
-
|
98
|
-
'order_by_st_3dlength' => 'order_by_st_length3d',
|
99
|
-
'order_by_st_3dperimeter' => 'order_by_st_perimeter3d',
|
100
|
-
'order_by_st_3dlength_spheroid' => 'order_by_st_length3d_spheroid'
|
101
|
-
}
|
58
|
+
require 'activerecord-spatial/spatial_scope_constants/postgis_legacy'
|
102
59
|
end
|
103
60
|
|
104
|
-
|
105
|
-
FUNCTION_ALIASES.merge!({
|
106
|
-
'st_3d_dwithin' => 'st_3ddwithin',
|
107
|
-
'st_3d_dfully_within' => 'st_3ddfullywithin',
|
108
|
-
'order_by_st_3d_distance' => 'order_by_st_3ddistance',
|
109
|
-
'order_by_st_3d_max_distance' => 'order_by_st_3dmaxdistance'
|
110
|
-
})
|
111
|
-
end
|
61
|
+
constants.each(&:freeze)
|
112
62
|
end
|
113
63
|
end
|
114
|
-
|
@@ -71,14 +71,14 @@ module ActiveRecordSpatial
|
|
71
71
|
# When wrapping a geometry column in a function, you can set the name of
|
72
72
|
# the function and its methods like so:
|
73
73
|
#
|
74
|
-
# Foo.st_within(geom, :
|
75
|
-
# :
|
76
|
-
# :
|
74
|
+
# Foo.st_within(geom, column: {
|
75
|
+
# name: :the_geom,
|
76
|
+
# wrapper: :centroid
|
77
77
|
# })
|
78
78
|
#
|
79
|
-
# Foo.st_within(geom, :
|
80
|
-
# :
|
81
|
-
# :
|
79
|
+
# Foo.st_within(geom, column: {
|
80
|
+
# wrapper: {
|
81
|
+
# snap: [ 'POINT (0 0)', 1 ]
|
82
82
|
# }
|
83
83
|
# })
|
84
84
|
#
|
@@ -131,126 +131,120 @@ module ActiveRecordSpatial
|
|
131
131
|
extend ActiveSupport::Concern
|
132
132
|
|
133
133
|
DEFAULT_OPTIONS = {
|
134
|
-
:
|
135
|
-
:
|
134
|
+
column: ActiveRecordSpatial.default_column_name,
|
135
|
+
use_index: true
|
136
136
|
}.freeze
|
137
137
|
|
138
138
|
included do
|
139
|
-
assert_arguments_length = proc
|
140
|
-
raise ArgumentError
|
141
|
-
|
142
|
-
}
|
139
|
+
assert_arguments_length = proc do |args, min, max = (1.0 / 0.0)|
|
140
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for #{min}-#{max})" unless args.length.between?(min, max)
|
141
|
+
end
|
143
142
|
|
144
143
|
SpatialScopeConstants::RELATIONSHIPS.each do |relationship|
|
145
|
-
|
144
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
146
145
|
scope :st_#{relationship}, lambda { |geom, options = {}|
|
147
146
|
options = {
|
148
|
-
:
|
147
|
+
geom_arg: geom
|
149
148
|
}.merge(options)
|
150
149
|
|
151
150
|
unless geom.nil?
|
152
|
-
|
151
|
+
where(
|
153
152
|
ActiveRecordSpatial::SpatialFunction.build!(self, '#{relationship}', options).to_sql
|
154
153
|
)
|
155
154
|
end
|
156
155
|
}
|
157
|
-
|
158
|
-
self.class_eval(src, __FILE__, line)
|
156
|
+
RUBY
|
159
157
|
end
|
160
158
|
|
161
159
|
SpatialScopeConstants::ONE_GEOMETRY_ARGUMENT_AND_ONE_ARGUMENT_RELATIONSHIPS.each do |relationship|
|
162
|
-
|
160
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
163
161
|
scope :st_#{relationship}, lambda { |geom, distance, options = {}|
|
164
162
|
options = {
|
165
|
-
:
|
166
|
-
:
|
163
|
+
geom_arg: geom,
|
164
|
+
args: distance
|
167
165
|
}.merge(options)
|
168
166
|
|
169
|
-
|
167
|
+
where(
|
170
168
|
ActiveRecordSpatial::SpatialFunction.build!(self, '#{relationship}', options).to_sql
|
171
169
|
)
|
172
170
|
}
|
173
|
-
|
174
|
-
self.class_eval(src, __FILE__, line)
|
171
|
+
RUBY
|
175
172
|
end
|
176
173
|
|
177
|
-
|
174
|
+
class_eval do
|
178
175
|
scope :st_geometry_type, lambda { |*args|
|
179
176
|
assert_arguments_length[args, 1]
|
180
177
|
options = args.extract_options!
|
181
178
|
types = args
|
182
179
|
|
183
|
-
|
180
|
+
where(
|
184
181
|
ActiveRecordSpatial::SpatialFunction.build!(self, 'GeometryType', options).in(types).to_sql
|
185
182
|
)
|
186
183
|
}
|
187
184
|
end
|
188
185
|
|
189
186
|
SpatialScopeConstants::ZERO_ARGUMENT_MEASUREMENTS.each do |measurement|
|
190
|
-
|
187
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
191
188
|
scope :order_by_st_#{measurement}, lambda { |options = {}|
|
192
189
|
if options.is_a?(Symbol)
|
193
190
|
options = {
|
194
|
-
:
|
191
|
+
desc: options
|
195
192
|
}
|
196
193
|
end
|
197
194
|
|
198
195
|
function_call = ActiveRecordSpatial::SpatialFunction.build!(self, '#{measurement}', options).to_sql
|
199
196
|
function_call << ActiveRecordSpatial::SpatialFunction.additional_ordering(options)
|
200
197
|
|
201
|
-
|
198
|
+
order(function_call)
|
202
199
|
}
|
203
|
-
|
204
|
-
self.class_eval(src, __FILE__, line)
|
200
|
+
RUBY
|
205
201
|
end
|
206
202
|
|
207
203
|
SpatialScopeConstants::ONE_GEOMETRY_ARGUMENT_MEASUREMENTS.each do |measurement|
|
208
|
-
|
204
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
209
205
|
scope :order_by_st_#{measurement}, lambda { |geom, options = {}|
|
210
206
|
if options.is_a?(Symbol)
|
211
207
|
options = {
|
212
|
-
:
|
208
|
+
desc: options
|
213
209
|
}
|
214
210
|
end
|
215
211
|
|
216
212
|
options = {
|
217
|
-
:
|
213
|
+
geom_arg: geom
|
218
214
|
}.merge(options)
|
219
215
|
|
220
216
|
function_call = ActiveRecordSpatial::SpatialFunction.build!(self, '#{measurement}', options).to_sql
|
221
217
|
function_call << ActiveRecordSpatial::SpatialFunction.additional_ordering(options)
|
222
218
|
|
223
|
-
|
219
|
+
order(function_call)
|
224
220
|
}
|
225
|
-
|
226
|
-
self.class_eval(src, __FILE__, line)
|
221
|
+
RUBY
|
227
222
|
end
|
228
223
|
|
229
224
|
SpatialScopeConstants::ONE_ARGUMENT_MEASUREMENTS.each do |measurement|
|
230
|
-
|
225
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
231
226
|
scope :order_by_st_#{measurement}, lambda { |argument, options = {}|
|
232
227
|
options = {
|
233
|
-
:
|
228
|
+
args: argument
|
234
229
|
}.merge(options)
|
235
230
|
|
236
231
|
function_call = ActiveRecordSpatial::SpatialFunction.build!(self, '#{measurement}', options).to_sql
|
237
232
|
function_call << ActiveRecordSpatial::SpatialFunction.additional_ordering(options)
|
238
233
|
|
239
|
-
|
234
|
+
order(function_call)
|
240
235
|
}
|
241
|
-
|
242
|
-
self.class_eval(src, __FILE__, line)
|
236
|
+
RUBY
|
243
237
|
end
|
244
238
|
|
245
|
-
|
239
|
+
class_eval do
|
246
240
|
scope :order_by_st_hausdorffdistance, lambda { |*args|
|
247
241
|
assert_arguments_length[args, 1, 3]
|
248
242
|
options = args.extract_options!
|
249
243
|
geom, densify_frac = args
|
250
244
|
|
251
245
|
options = {
|
252
|
-
:
|
253
|
-
:
|
246
|
+
geom_arg: geom,
|
247
|
+
args: densify_frac
|
254
248
|
}.merge(options)
|
255
249
|
|
256
250
|
function_call = ActiveRecordSpatial::SpatialFunction.build!(
|
@@ -260,23 +254,27 @@ module ActiveRecordSpatial
|
|
260
254
|
).to_sql
|
261
255
|
function_call << ActiveRecordSpatial::SpatialFunction.additional_ordering(options)
|
262
256
|
|
263
|
-
|
257
|
+
order(function_call)
|
264
258
|
}
|
265
259
|
|
266
260
|
scope :order_by_st_distance_spheroid, lambda { |geom, spheroid, options = {}|
|
267
261
|
options = {
|
268
|
-
:
|
269
|
-
:
|
262
|
+
geom_arg: geom,
|
263
|
+
args: spheroid
|
270
264
|
}.merge(options)
|
271
265
|
|
272
266
|
function_call = ActiveRecordSpatial::SpatialFunction.build!(
|
273
267
|
self,
|
274
|
-
'
|
268
|
+
if ActiveRecordSpatial::POSTGIS[:lib] >= '2.2'
|
269
|
+
'distancespheroid'
|
270
|
+
else
|
271
|
+
'distance_spheroid'
|
272
|
+
end,
|
275
273
|
options
|
276
274
|
).to_sql
|
277
275
|
function_call << ActiveRecordSpatial::SpatialFunction.additional_ordering(options)
|
278
276
|
|
279
|
-
|
277
|
+
order(function_call)
|
280
278
|
}
|
281
279
|
|
282
280
|
class << self
|