rgeo-ar 0.6.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 +7 -0
- data/History.rdoc +98 -0
- data/README.rdoc +95 -0
- data/lib/rgeo/active_record/adapter_test_helper.rb +186 -0
- data/lib/rgeo/active_record/ar_factory_settings.rb +229 -0
- data/lib/rgeo/active_record/arel_spatial_queries.rb +215 -0
- data/lib/rgeo/active_record/common_adapter_elements.rb +177 -0
- data/lib/rgeo/active_record/geometry_mixin.rb +108 -0
- data/lib/rgeo/active_record/spatial_expressions.rb +314 -0
- data/lib/rgeo/active_record/task_hacker.rb +105 -0
- data/lib/rgeo/active_record/version.rb +39 -0
- data/lib/rgeo/active_record.rb +83 -0
- data/lib/rgeo-activerecord.rb +36 -0
- data/test/support/fake_record.rb +124 -0
- data/test/tc_basic.rb +109 -0
- data/test/test_helper.rb +10 -0
- metadata +133 -0
@@ -0,0 +1,314 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Spatial expressions for Arel
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010-2012 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
module RGeo
|
38
|
+
|
39
|
+
module ActiveRecord
|
40
|
+
|
41
|
+
|
42
|
+
# Returns true if spatial expressions (i.e. the methods in the
|
43
|
+
# SpatialExpressions module) are supported. Generally, this is true
|
44
|
+
# if Arel is at version 2.1 or later.
|
45
|
+
|
46
|
+
def self.spatial_expressions_supported?
|
47
|
+
defined?(::Arel::Nodes::NamedFunction)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# A set of spatial expression builders.
|
52
|
+
# These methods can be chained off other spatial expressions to form
|
53
|
+
# complex expressions.
|
54
|
+
#
|
55
|
+
# These functions require Arel 2.1 or later.
|
56
|
+
|
57
|
+
module SpatialExpressions
|
58
|
+
|
59
|
+
|
60
|
+
#--
|
61
|
+
# Generic functions
|
62
|
+
#++
|
63
|
+
|
64
|
+
def st_function(function_, *args_)
|
65
|
+
spatial_info_ = args_.last.is_a?(::Array) ? args_.pop : []
|
66
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new(function_, [self] + args_, spatial_info_)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
#--
|
71
|
+
# Geometry functions
|
72
|
+
#++
|
73
|
+
|
74
|
+
def st_dimension
|
75
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Dimension', [self], [false, true])
|
76
|
+
end
|
77
|
+
|
78
|
+
def st_geometrytype
|
79
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_GeometryType', [self], [false, true])
|
80
|
+
end
|
81
|
+
|
82
|
+
def st_astext
|
83
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_AsText', [self], [false, true])
|
84
|
+
end
|
85
|
+
|
86
|
+
def st_asbinary
|
87
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_AsBinary', [self], [false, true])
|
88
|
+
end
|
89
|
+
|
90
|
+
def st_srid
|
91
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_SRID', [self], [false, true])
|
92
|
+
end
|
93
|
+
|
94
|
+
def st_isempty
|
95
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_IsEmpty', [self], [false, true])
|
96
|
+
end
|
97
|
+
|
98
|
+
def st_issimple
|
99
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_IsSimple', [self], [false, true])
|
100
|
+
end
|
101
|
+
|
102
|
+
def st_boundary
|
103
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Boundary', [self], [true, true])
|
104
|
+
end
|
105
|
+
|
106
|
+
def st_envelope
|
107
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Envelope', [self], [true, true])
|
108
|
+
end
|
109
|
+
|
110
|
+
def st_equals(rhs_)
|
111
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Equals', [self, rhs_], [false, true, true])
|
112
|
+
end
|
113
|
+
|
114
|
+
def st_disjoint(rhs_)
|
115
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Disjoint', [self, rhs_], [false, true, true])
|
116
|
+
end
|
117
|
+
|
118
|
+
def st_intersects(rhs_)
|
119
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Intersects', [self, rhs_], [false, true, true])
|
120
|
+
end
|
121
|
+
|
122
|
+
def st_touches(rhs_)
|
123
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Touches', [self, rhs_], [false, true, true])
|
124
|
+
end
|
125
|
+
|
126
|
+
def st_crosses(rhs_)
|
127
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Crosses', [self, rhs_], [false, true, true])
|
128
|
+
end
|
129
|
+
|
130
|
+
def st_within(rhs_)
|
131
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Within', [self, rhs_], [false, true, true])
|
132
|
+
end
|
133
|
+
|
134
|
+
def st_contains(rhs_)
|
135
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Contains', [self, rhs_], [false, true, true])
|
136
|
+
end
|
137
|
+
|
138
|
+
def st_overlaps(rhs_)
|
139
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Overlaps', [self, rhs_], [false, true, true])
|
140
|
+
end
|
141
|
+
|
142
|
+
def st_relate(rhs_, matrix_=nil)
|
143
|
+
args_ = [self, rhs_]
|
144
|
+
args_ << matrix.to_s if matrix_
|
145
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Relate', args_, [false, true, true, false])
|
146
|
+
end
|
147
|
+
|
148
|
+
def st_distance(rhs_, units_=nil)
|
149
|
+
args_ = [self, rhs_]
|
150
|
+
args_ << units.to_s if units_
|
151
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Distance', args_, [false, true, true, false])
|
152
|
+
end
|
153
|
+
|
154
|
+
def st_intersection(rhs_)
|
155
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Intersection', [self, rhs_], [true, true, true])
|
156
|
+
end
|
157
|
+
|
158
|
+
def st_difference(rhs_)
|
159
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Difference', [self, rhs_], [true, true, true])
|
160
|
+
end
|
161
|
+
|
162
|
+
def st_union(rhs_)
|
163
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Union', [self, rhs_], [true, true, true])
|
164
|
+
end
|
165
|
+
|
166
|
+
def st_symdifference(rhs_)
|
167
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_SymDifference', [self, rhs_], [true, true, true])
|
168
|
+
end
|
169
|
+
|
170
|
+
def st_buffer(distance_, units_=nil)
|
171
|
+
args_ = [self, distance_.to_f]
|
172
|
+
args_ << units.to_s if units_
|
173
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Buffer', args_, [true, true, false])
|
174
|
+
end
|
175
|
+
|
176
|
+
def st_convexhull
|
177
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_ConvexHull', [self], [true, true])
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
#--
|
182
|
+
# Point functions
|
183
|
+
#++
|
184
|
+
|
185
|
+
def st_x
|
186
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_X', [self], [false, true])
|
187
|
+
end
|
188
|
+
|
189
|
+
def st_y
|
190
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Y', [self], [false, true])
|
191
|
+
end
|
192
|
+
|
193
|
+
def st_z
|
194
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Z', [self], [false, true])
|
195
|
+
end
|
196
|
+
|
197
|
+
def st_m
|
198
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_M', [self], [false, true])
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
#--
|
203
|
+
# Curve functions
|
204
|
+
#++
|
205
|
+
|
206
|
+
def st_startpoint
|
207
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_StartPoint', [self], [true, true])
|
208
|
+
end
|
209
|
+
|
210
|
+
def st_endpoint
|
211
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_EndPoint', [self], [true, true])
|
212
|
+
end
|
213
|
+
|
214
|
+
def st_isclosed
|
215
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_IsClosed', [self], [false, true])
|
216
|
+
end
|
217
|
+
|
218
|
+
def st_isring
|
219
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_IsRing', [self], [false, true])
|
220
|
+
end
|
221
|
+
|
222
|
+
def st_length(units_=nil)
|
223
|
+
args_ = [self]
|
224
|
+
args_ << units.to_s if units_
|
225
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Length', args_, [false, true, false])
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
#--
|
230
|
+
# LineString functions
|
231
|
+
#++
|
232
|
+
|
233
|
+
def st_numpoints
|
234
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_NumPoints', [self], [false, true])
|
235
|
+
end
|
236
|
+
|
237
|
+
def st_pointn(n_)
|
238
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_PointN', [self, n_.to_i], [true, true, false])
|
239
|
+
end
|
240
|
+
|
241
|
+
|
242
|
+
#--
|
243
|
+
# Surface functions
|
244
|
+
#++
|
245
|
+
|
246
|
+
def st_area(units_=nil)
|
247
|
+
args_ = [self]
|
248
|
+
args_ << units.to_s if units_
|
249
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_StartPoint', args_, [false, true, false])
|
250
|
+
end
|
251
|
+
|
252
|
+
def st_centroid
|
253
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Centroid', [self], [true, true])
|
254
|
+
end
|
255
|
+
|
256
|
+
def st_pointonsurface
|
257
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_PointOnSurface', [self], [true, true])
|
258
|
+
end
|
259
|
+
|
260
|
+
|
261
|
+
#--
|
262
|
+
# Polygon functions
|
263
|
+
#++
|
264
|
+
|
265
|
+
def st_exteriorring
|
266
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_ExteriorRing', [self], [true, true])
|
267
|
+
end
|
268
|
+
|
269
|
+
def st_numinteriorrings
|
270
|
+
# Note: the name difference is intentional. The standard
|
271
|
+
# names this function incorrectly.
|
272
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_NumInteriorRing', [self], [false, true])
|
273
|
+
end
|
274
|
+
|
275
|
+
def st_interiorringn(n_)
|
276
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_InteriorRingN', [self, n_.to_i], [true, true, false])
|
277
|
+
end
|
278
|
+
|
279
|
+
|
280
|
+
#--
|
281
|
+
# GeometryCollection functions
|
282
|
+
#++
|
283
|
+
|
284
|
+
def st_numgeometries
|
285
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_NumGeometries', [self], [false, true])
|
286
|
+
end
|
287
|
+
|
288
|
+
def st_geometryn(n_)
|
289
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_GeometryN', [self, n_.to_i], [true, true, false])
|
290
|
+
end
|
291
|
+
|
292
|
+
|
293
|
+
end
|
294
|
+
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
module Arel
|
302
|
+
|
303
|
+
# Create a spatial constant node.
|
304
|
+
# This node wraps a spatial value (such as an RGeo feature or a text
|
305
|
+
# string in WKT format). It supports chaining with the functions
|
306
|
+
# defined by RGeo::ActiveRecord::SpatialExpressions.
|
307
|
+
#
|
308
|
+
# Requires Arel 2.1 or later.
|
309
|
+
|
310
|
+
def self.spatial(arg_)
|
311
|
+
::RGeo::ActiveRecord::SpatialConstantNode.new(arg_)
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# A tool for hacking ActiveRecord's rake tasks
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010-2012 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
module RGeo
|
38
|
+
|
39
|
+
module ActiveRecord
|
40
|
+
|
41
|
+
|
42
|
+
# A set of tools for hacking ActiveRecord's Rake tasks.
|
43
|
+
|
44
|
+
module TaskHacker
|
45
|
+
|
46
|
+
|
47
|
+
class Action # :nodoc:
|
48
|
+
|
49
|
+
def initialize(env_, pattern_, proc_)
|
50
|
+
@env = env_
|
51
|
+
@pattern = pattern_
|
52
|
+
@proc = proc_
|
53
|
+
end
|
54
|
+
|
55
|
+
def call(task_)
|
56
|
+
env_ = @env || ::Rails.env || 'development'
|
57
|
+
config_ = ::ActiveRecord::Base.configurations[env_]
|
58
|
+
if config_
|
59
|
+
if @pattern === config_['adapter']
|
60
|
+
task_.actions.delete_if{ |a_| a_ != self }
|
61
|
+
@proc.call(config_)
|
62
|
+
end
|
63
|
+
else
|
64
|
+
puts "WARNING: Could not find environment #{env_.inspect} in your database.yml"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def arity
|
69
|
+
1
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
class << self
|
76
|
+
|
77
|
+
|
78
|
+
# Modify a named ActiveRecord rake task.
|
79
|
+
# The task must be of the form that hinges on the database adapter
|
80
|
+
# name. You must provide the fully-qualified name of the rake task
|
81
|
+
# to modify, the Rails environment for which to get the database
|
82
|
+
# configuration (which may be nil to use the current Rails.env),
|
83
|
+
# a Regexp or String identifying the adapter name for which to
|
84
|
+
# modify the rake task, and a block. If the database adapter
|
85
|
+
# associated with the given environment matches the given pattern,
|
86
|
+
# then the rake task's action(s) will be replaced by the given
|
87
|
+
# block. The block will be passed the environment's database
|
88
|
+
# configuration hash.
|
89
|
+
|
90
|
+
def modify(name_, env_, pattern_, &block_)
|
91
|
+
if ::Rake::Task.task_defined?(name_)
|
92
|
+
::Rake::Task[name_].actions.unshift(Action.new(env_, pattern_, block_))
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Version of rgeo-activerecord
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010-2012 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
|
35
|
+
module RGeo
|
36
|
+
module ActiveRecord
|
37
|
+
VERSION = '0.6.0'.freeze
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# ActiveRecord extensions for RGeo
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010-2012 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
# Dependencies
|
38
|
+
require 'rgeo'
|
39
|
+
require 'active_record'
|
40
|
+
|
41
|
+
|
42
|
+
# RGeo is a spatial data library for Ruby, provided by the "rgeo" gem.
|
43
|
+
#
|
44
|
+
# The optional RGeo::ActiveRecord module provides spatial extensions for
|
45
|
+
# ActiveRecord, and a set of tools and helpers for writing RGeo-based
|
46
|
+
# spatial connection adapters.
|
47
|
+
|
48
|
+
module RGeo
|
49
|
+
|
50
|
+
|
51
|
+
# This module contains a set of ActiveRecord extensions for RGeo.
|
52
|
+
# Generally, you will not need to interact with the contents of this
|
53
|
+
# module directly, unless you are writing a spatial ActiveRecord
|
54
|
+
# connection adapter.
|
55
|
+
|
56
|
+
module ActiveRecord
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
# The rgeo-activerecord gem installs several patches to Arel to provide
|
64
|
+
# support for spatial queries.
|
65
|
+
|
66
|
+
module Arel
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# The rgeo-activerecord gem installs several patches to ActiveRecord
|
71
|
+
# to support services needed by spatial adapters.
|
72
|
+
|
73
|
+
module ActiveRecord
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
# Implementation files
|
78
|
+
require 'rgeo/active_record/version.rb'
|
79
|
+
require 'rgeo/active_record/spatial_expressions.rb'
|
80
|
+
require 'rgeo/active_record/arel_spatial_queries'
|
81
|
+
require 'rgeo/active_record/common_adapter_elements.rb'
|
82
|
+
require 'rgeo/active_record/ar_factory_settings'
|
83
|
+
require 'rgeo/active_record/geometry_mixin'
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# ActiveRecord extensions for RGeo
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010-2012 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
require 'rgeo/active_record'
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# From https://github.com/rails/arel/blob/4-0-stable/test/support/fake_record.rb
|
2
|
+
module FakeRecord
|
3
|
+
class Column < Struct.new(:name, :type)
|
4
|
+
end
|
5
|
+
|
6
|
+
class Connection
|
7
|
+
attr_reader :tables
|
8
|
+
attr_accessor :visitor
|
9
|
+
|
10
|
+
def initialize(visitor = nil)
|
11
|
+
@tables = %w{ users photos developers products}
|
12
|
+
@columns = {
|
13
|
+
'users' => [
|
14
|
+
Column.new('id', :integer),
|
15
|
+
Column.new('name', :string),
|
16
|
+
Column.new('bool', :boolean),
|
17
|
+
Column.new('created_at', :date)
|
18
|
+
],
|
19
|
+
'products' => [
|
20
|
+
Column.new('id', :integer),
|
21
|
+
Column.new('price', :decimal)
|
22
|
+
]
|
23
|
+
}
|
24
|
+
@columns_hash = {
|
25
|
+
'users' => Hash[@columns['users'].map { |x| [x.name, x] }],
|
26
|
+
'products' => Hash[@columns['products'].map { |x| [x.name, x] }]
|
27
|
+
}
|
28
|
+
@primary_keys = {
|
29
|
+
'users' => 'id',
|
30
|
+
'products' => 'id'
|
31
|
+
}
|
32
|
+
@visitor = visitor
|
33
|
+
end
|
34
|
+
|
35
|
+
def columns_hash table_name
|
36
|
+
@columns_hash[table_name]
|
37
|
+
end
|
38
|
+
|
39
|
+
def primary_key name
|
40
|
+
@primary_keys[name.to_s]
|
41
|
+
end
|
42
|
+
|
43
|
+
def table_exists? name
|
44
|
+
@tables.include? name.to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
def columns name, message = nil
|
48
|
+
@columns[name.to_s]
|
49
|
+
end
|
50
|
+
|
51
|
+
def quote_table_name name
|
52
|
+
"\"#{name.to_s}\""
|
53
|
+
end
|
54
|
+
|
55
|
+
def quote_column_name name
|
56
|
+
"\"#{name.to_s}\""
|
57
|
+
end
|
58
|
+
|
59
|
+
def schema_cache
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def quote thing, column = nil
|
64
|
+
if column && column.type == :integer
|
65
|
+
return 'NULL' if thing.nil?
|
66
|
+
return thing.to_i
|
67
|
+
end
|
68
|
+
|
69
|
+
case thing
|
70
|
+
when true
|
71
|
+
"'t'"
|
72
|
+
when false
|
73
|
+
"'f'"
|
74
|
+
when nil
|
75
|
+
'NULL'
|
76
|
+
when Numeric
|
77
|
+
thing
|
78
|
+
else
|
79
|
+
"'#{thing}'"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class ConnectionPool
|
85
|
+
class Spec < Struct.new(:config)
|
86
|
+
end
|
87
|
+
|
88
|
+
attr_reader :spec, :connection
|
89
|
+
|
90
|
+
def initialize
|
91
|
+
@spec = Spec.new(:adapter => 'america')
|
92
|
+
@connection = Connection.new
|
93
|
+
@connection.visitor = Arel::Visitors::ToSql.new(connection)
|
94
|
+
end
|
95
|
+
|
96
|
+
def with_connection
|
97
|
+
yield connection
|
98
|
+
end
|
99
|
+
|
100
|
+
def table_exists? name
|
101
|
+
connection.tables.include? name.to_s
|
102
|
+
end
|
103
|
+
|
104
|
+
def columns_hash
|
105
|
+
connection.columns_hash
|
106
|
+
end
|
107
|
+
|
108
|
+
def schema_cache
|
109
|
+
connection
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class Base
|
114
|
+
attr_accessor :connection_pool
|
115
|
+
|
116
|
+
def initialize
|
117
|
+
@connection_pool = ConnectionPool.new
|
118
|
+
end
|
119
|
+
|
120
|
+
def connection
|
121
|
+
connection_pool.connection
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|