rgeo-activerecord 0.4.1 → 0.4.2
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.
- data/History.rdoc +5 -0
- data/README.rdoc +4 -4
- data/Version +1 -1
- data/lib/rgeo-activerecord.rb +36 -0
- data/lib/rgeo/active_record.rb +13 -13
- data/lib/rgeo/active_record/adapter_test_helper.rb +33 -33
- data/lib/rgeo/active_record/ar_factory_settings.rb +75 -71
- data/lib/rgeo/active_record/arel_spatial_queries.rb +63 -63
- data/lib/rgeo/active_record/common_adapter_elements.rb +36 -36
- data/lib/rgeo/active_record/geometry_mixin.rb +30 -30
- data/lib/rgeo/active_record/spatial_expressions.rb +86 -86
- data/lib/rgeo/active_record/task_hacker.rb +30 -30
- data/lib/rgeo/active_record/version.rb +12 -12
- data/test/tc_basic.rb +34 -30
- metadata +11 -10
@@ -1,15 +1,15 @@
|
|
1
1
|
# -----------------------------------------------------------------------------
|
2
|
-
#
|
2
|
+
#
|
3
3
|
# Various Arel hacks to support spatial queries
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# -----------------------------------------------------------------------------
|
6
|
-
# Copyright 2010 Daniel Azuma
|
7
|
-
#
|
6
|
+
# Copyright 2010-2012 Daniel Azuma
|
7
|
+
#
|
8
8
|
# All rights reserved.
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# Redistribution and use in source and binary forms, with or without
|
11
11
|
# modification, are permitted provided that the following conditions are met:
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# * Redistributions of source code must retain the above copyright notice,
|
14
14
|
# this list of conditions and the following disclaimer.
|
15
15
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
@@ -18,7 +18,7 @@
|
|
18
18
|
# * Neither the name of the copyright holder, nor the names of any other
|
19
19
|
# contributors to this software, may be used to endorse or promote products
|
20
20
|
# derived from this software without specific prior written permission.
|
21
|
-
#
|
21
|
+
#
|
22
22
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
23
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
24
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
@@ -35,33 +35,33 @@
|
|
35
35
|
|
36
36
|
|
37
37
|
module RGeo
|
38
|
-
|
38
|
+
|
39
39
|
module ActiveRecord
|
40
|
-
|
41
|
-
|
40
|
+
|
41
|
+
|
42
42
|
# A set of common Arel visitor hacks for spatial ToSql visitors.
|
43
43
|
# Generally, a spatial ActiveRecord adapter should provide a custom
|
44
44
|
# ToSql Arel visitor that includes and customizes this module.
|
45
45
|
# See the existing spatial adapters (i.e. postgis, spatialite,
|
46
46
|
# mysqlspatial, and mysql2spatial) for usage examples.
|
47
|
-
|
47
|
+
|
48
48
|
module SpatialToSql
|
49
|
-
|
50
|
-
|
49
|
+
|
50
|
+
|
51
51
|
# Map a standard OGC SQL function name to the actual name used by
|
52
52
|
# a particular database. This method should take a name and
|
53
53
|
# return either the changed name or the original name.
|
54
|
-
|
54
|
+
|
55
55
|
def st_func(standard_name_)
|
56
56
|
standard_name_
|
57
57
|
end
|
58
|
-
|
59
|
-
|
58
|
+
|
59
|
+
|
60
60
|
# Visit the SpatialNamedFunction node. This operates similarly to
|
61
61
|
# the standard NamedFunction node, but it performs function name
|
62
62
|
# mapping for the database, and it also uses the type information
|
63
63
|
# in the node to determine when to cast string arguments to WKT,
|
64
|
-
|
64
|
+
|
65
65
|
def visit_RGeo_ActiveRecord_SpatialNamedFunction(node_)
|
66
66
|
name_ = st_func(node_.name)
|
67
67
|
exprs_ = []
|
@@ -70,12 +70,12 @@ module RGeo
|
|
70
70
|
end
|
71
71
|
"#{name_}(#{node_.distinct ? 'DISTINCT ' : ''}#{exprs_.join(', ')})#{node_.alias ? " AS #{visit node_.alias}" : ''}"
|
72
72
|
end
|
73
|
-
|
74
|
-
|
73
|
+
|
74
|
+
|
75
75
|
# Generates SQL for a spatial node.
|
76
76
|
# The node must be a string (in which case it is treated as WKT),
|
77
77
|
# an RGeo feature, or a spatial attribute.
|
78
|
-
|
78
|
+
|
79
79
|
def visit_in_spatial_context(node_)
|
80
80
|
case node_
|
81
81
|
when ::String
|
@@ -86,40 +86,40 @@ module RGeo
|
|
86
86
|
visit(node_)
|
87
87
|
end
|
88
88
|
end
|
89
|
-
|
90
|
-
|
89
|
+
|
90
|
+
|
91
91
|
end
|
92
|
-
|
93
|
-
|
92
|
+
|
93
|
+
|
94
94
|
# This node wraps an RGeo feature and gives it spatial expression
|
95
95
|
# constructors.
|
96
|
-
|
96
|
+
|
97
97
|
class SpatialConstantNode
|
98
|
-
|
98
|
+
|
99
99
|
include ::RGeo::ActiveRecord::SpatialExpressions
|
100
|
-
|
101
|
-
|
100
|
+
|
101
|
+
|
102
102
|
# The delegate should be the RGeo feature.
|
103
|
-
|
103
|
+
|
104
104
|
def initialize(delegate_)
|
105
105
|
@delegate = delegate_
|
106
106
|
end
|
107
|
-
|
108
|
-
|
107
|
+
|
108
|
+
|
109
109
|
# Return the RGeo feature
|
110
|
-
|
110
|
+
|
111
111
|
attr_reader :delegate
|
112
|
-
|
113
|
-
|
112
|
+
|
113
|
+
|
114
114
|
end
|
115
|
-
|
116
|
-
|
115
|
+
|
116
|
+
|
117
117
|
# :stopdoc:
|
118
|
-
|
119
|
-
|
118
|
+
|
119
|
+
|
120
120
|
# Hack Arel Attributes dispatcher to recognize geometry columns.
|
121
121
|
# This is deprecated but necessary to support legacy Arel versions.
|
122
|
-
|
122
|
+
|
123
123
|
if ::Arel::Attributes.method_defined?(:for)
|
124
124
|
module ArelAttributesLegacyClassMethods
|
125
125
|
def for(column_)
|
@@ -128,11 +128,11 @@ module RGeo
|
|
128
128
|
end
|
129
129
|
::Arel::Attributes.extend(ArelAttributesLegacyClassMethods)
|
130
130
|
end
|
131
|
-
|
132
|
-
|
131
|
+
|
132
|
+
|
133
133
|
# Make sure the standard Arel visitors can handle RGeo feature objects
|
134
134
|
# by default.
|
135
|
-
|
135
|
+
|
136
136
|
::Arel::Visitors::Visitor.class_eval do
|
137
137
|
def visit_RGeo_ActiveRecord_SpatialConstantNode(node_)
|
138
138
|
if respond_to?(:visit_in_spatial_context)
|
@@ -151,60 +151,60 @@ module RGeo
|
|
151
151
|
::Arel::Visitors::ToSql.class_eval do
|
152
152
|
alias :visit_RGeo_Feature_Instance :visit_String
|
153
153
|
end
|
154
|
-
|
155
|
-
|
154
|
+
|
155
|
+
|
156
156
|
# Add tools to build spatial structures in the AST.
|
157
157
|
# This stuff requires Arel 2.1 or later.
|
158
|
-
|
158
|
+
|
159
159
|
if defined?(::Arel::Nodes::NamedFunction)
|
160
|
-
|
160
|
+
|
161
161
|
# Allow chaining of predications from named functions
|
162
162
|
# (Some older versions of Arel didn't do this.)
|
163
163
|
::Arel::Nodes::NamedFunction.class_eval do
|
164
164
|
include ::Arel::Predications unless include?(::Arel::Predications)
|
165
165
|
end
|
166
|
-
|
166
|
+
|
167
167
|
# Allow chaining of spatial expressions from attributes
|
168
168
|
::Arel::Attribute.class_eval do
|
169
169
|
include ::RGeo::ActiveRecord::SpatialExpressions
|
170
170
|
end
|
171
|
-
|
172
|
-
|
171
|
+
|
172
|
+
|
173
173
|
# A NamedFunction subclass that keeps track of the spatial-ness of
|
174
174
|
# the arguments and return values, so that it can provide context to
|
175
175
|
# visitors that want to interpret syntax differently when dealing with
|
176
176
|
# spatial elements.
|
177
|
-
|
177
|
+
|
178
178
|
class SpatialNamedFunction < ::Arel::Nodes::NamedFunction
|
179
|
-
|
179
|
+
|
180
180
|
include ::RGeo::ActiveRecord::SpatialExpressions
|
181
|
-
|
181
|
+
|
182
182
|
def initialize(name_, expr_, spatial_flags_=[], aliaz_=nil)
|
183
183
|
super(name_, expr_, aliaz_)
|
184
184
|
@spatial_flags = spatial_flags_
|
185
185
|
end
|
186
|
-
|
186
|
+
|
187
187
|
def spatial_result?
|
188
188
|
@spatial_flags.first
|
189
189
|
end
|
190
|
-
|
190
|
+
|
191
191
|
def spatial_argument?(index_)
|
192
192
|
@spatial_flags[index_+1]
|
193
193
|
end
|
194
|
-
|
194
|
+
|
195
195
|
end
|
196
|
-
|
196
|
+
|
197
197
|
else
|
198
|
-
|
198
|
+
|
199
199
|
# A dummy SpatialNamedFunction for pre-2.1 versions of Arel.
|
200
200
|
class SpatialNamedFunction; end
|
201
|
-
|
201
|
+
|
202
202
|
end
|
203
|
-
|
204
|
-
|
203
|
+
|
204
|
+
|
205
205
|
# :startdoc:
|
206
|
-
|
207
|
-
|
206
|
+
|
207
|
+
|
208
208
|
end
|
209
|
-
|
209
|
+
|
210
210
|
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
# -----------------------------------------------------------------------------
|
2
|
-
#
|
2
|
+
#
|
3
3
|
# Common tools for spatial adapters for ActiveRecord
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# -----------------------------------------------------------------------------
|
6
|
-
# Copyright 2010 Daniel Azuma
|
7
|
-
#
|
6
|
+
# Copyright 2010-2012 Daniel Azuma
|
7
|
+
#
|
8
8
|
# All rights reserved.
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# Redistribution and use in source and binary forms, with or without
|
11
11
|
# modification, are permitted provided that the following conditions are met:
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# * Redistributions of source code must retain the above copyright notice,
|
14
14
|
# this list of conditions and the following disclaimer.
|
15
15
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
@@ -18,7 +18,7 @@
|
|
18
18
|
# * Neither the name of the copyright holder, nor the names of any other
|
19
19
|
# contributors to this software, may be used to endorse or promote products
|
20
20
|
# derived from this software without specific prior written permission.
|
21
|
-
#
|
21
|
+
#
|
22
22
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
23
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
24
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
@@ -40,13 +40,13 @@ require 'active_record'
|
|
40
40
|
|
41
41
|
|
42
42
|
module RGeo
|
43
|
-
|
43
|
+
|
44
44
|
module ActiveRecord
|
45
|
-
|
46
|
-
|
45
|
+
|
46
|
+
|
47
47
|
# Some default column constructors specifications for most spatial
|
48
48
|
# databases. Individual adapters may add to or override this list.
|
49
|
-
|
49
|
+
|
50
50
|
DEFAULT_SPATIAL_COLUMN_CONSTRUCTORS = {
|
51
51
|
:spatial => {:type => 'geometry'}.freeze,
|
52
52
|
:geometry => {}.freeze,
|
@@ -58,16 +58,16 @@ module RGeo
|
|
58
58
|
:multi_point => {}.freeze,
|
59
59
|
:multi_polygon => {}.freeze,
|
60
60
|
}.freeze
|
61
|
-
|
62
|
-
|
61
|
+
|
62
|
+
|
63
63
|
# Index definition struct with a spatial flag field.
|
64
|
-
|
64
|
+
|
65
65
|
class SpatialIndexDefinition < ::Struct.new(:table, :name, :unique, :columns, :lengths, :spatial)
|
66
66
|
end
|
67
|
-
|
68
|
-
|
67
|
+
|
68
|
+
|
69
69
|
# Returns a feature type module given a string type.
|
70
|
-
|
70
|
+
|
71
71
|
def self.geometric_type_from_name(name_)
|
72
72
|
case name_.to_s
|
73
73
|
when /^geometry/i then ::RGeo::Feature::Geometry
|
@@ -81,13 +81,13 @@ module RGeo
|
|
81
81
|
else nil
|
82
82
|
end
|
83
83
|
end
|
84
|
-
|
85
|
-
|
84
|
+
|
85
|
+
|
86
86
|
# :stopdoc:
|
87
|
-
|
88
|
-
|
87
|
+
|
88
|
+
|
89
89
|
# Provide methods for each geometric subtype during table definitions.
|
90
|
-
|
90
|
+
|
91
91
|
::ActiveRecord::ConnectionAdapters::TableDefinition.class_eval do
|
92
92
|
alias_method :method_missing_without_rgeo_modification, :method_missing
|
93
93
|
def method_missing(method_name_, *args_, &block_)
|
@@ -103,10 +103,10 @@ module RGeo
|
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
106
|
-
|
107
|
-
|
106
|
+
|
107
|
+
|
108
108
|
# Provide methods for each geometric subtype during table changes.
|
109
|
-
|
109
|
+
|
110
110
|
::ActiveRecord::ConnectionAdapters::Table.class_eval do
|
111
111
|
alias_method :method_missing_without_rgeo_modification, :method_missing
|
112
112
|
def method_missing(method_name_, *args_, &block_)
|
@@ -122,10 +122,10 @@ module RGeo
|
|
122
122
|
end
|
123
123
|
end
|
124
124
|
end
|
125
|
-
|
126
|
-
|
125
|
+
|
126
|
+
|
127
127
|
# Hack schema dumper to output spatial index flag
|
128
|
-
|
128
|
+
|
129
129
|
::ActiveRecord::SchemaDumper.class_eval do
|
130
130
|
private
|
131
131
|
def indexes(table_, stream_)
|
@@ -147,17 +147,17 @@ module RGeo
|
|
147
147
|
end
|
148
148
|
end
|
149
149
|
end
|
150
|
-
|
151
|
-
|
150
|
+
|
151
|
+
|
152
152
|
# Tell ActiveRecord to cache spatial attribute values so they don't get
|
153
153
|
# re-parsed on every access.
|
154
|
-
|
154
|
+
|
155
155
|
::ActiveRecord::Base.attribute_types_cached_by_default << :spatial
|
156
|
-
|
157
|
-
|
156
|
+
|
157
|
+
|
158
158
|
# :startdoc:
|
159
|
-
|
160
|
-
|
159
|
+
|
160
|
+
|
161
161
|
end
|
162
|
-
|
162
|
+
|
163
163
|
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
# -----------------------------------------------------------------------------
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
2
|
+
#
|
3
|
+
# Geometry mixin for JSON serialization
|
4
|
+
#
|
5
5
|
# -----------------------------------------------------------------------------
|
6
|
-
# Copyright 2010 Daniel Azuma
|
7
|
-
#
|
6
|
+
# Copyright 2010-2012 Daniel Azuma
|
7
|
+
#
|
8
8
|
# All rights reserved.
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# Redistribution and use in source and binary forms, with or without
|
11
11
|
# modification, are permitted provided that the following conditions are met:
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# * Redistributions of source code must retain the above copyright notice,
|
14
14
|
# this list of conditions and the following disclaimer.
|
15
15
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
@@ -18,7 +18,7 @@
|
|
18
18
|
# * Neither the name of the copyright holder, nor the names of any other
|
19
19
|
# contributors to this software, may be used to endorse or promote products
|
20
20
|
# derived from this software without specific prior written permission.
|
21
|
-
#
|
21
|
+
#
|
22
22
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
23
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
24
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
@@ -35,35 +35,35 @@
|
|
35
35
|
|
36
36
|
|
37
37
|
module RGeo
|
38
|
-
|
38
|
+
|
39
39
|
module ActiveRecord
|
40
|
-
|
41
|
-
|
40
|
+
|
41
|
+
|
42
42
|
# This module is mixed into all geometry objects. It provides an
|
43
43
|
# as_json method so that ActiveRecord knows how to generate JSON
|
44
44
|
# for a geometry-valued field.
|
45
|
-
|
45
|
+
|
46
46
|
module GeometryMixin
|
47
|
-
|
48
|
-
|
47
|
+
|
48
|
+
|
49
49
|
# The default JSON generator Proc. Renders geometry fields as WKT.
|
50
50
|
DEFAULT_JSON_GENERATOR = ::Proc.new{ |geom_| geom_.to_s }
|
51
|
-
|
51
|
+
|
52
52
|
@json_generator = DEFAULT_JSON_GENERATOR
|
53
|
-
|
54
|
-
|
53
|
+
|
54
|
+
|
55
55
|
# Set the style of JSON generation used for geometry fields in an
|
56
56
|
# ActiveRecord model by default. You may pass nil to use
|
57
57
|
# DEFAULT_JSON_GENERATOR, a proc that takes a geometry as the
|
58
58
|
# argument and returns an object that can be converted to JSON
|
59
59
|
# (i.e. usually a hash or string), or one of the following symbolic
|
60
60
|
# values:
|
61
|
-
#
|
61
|
+
#
|
62
62
|
# <tt>:wkt</tt>::
|
63
63
|
# Well-known text format. (Same as DEFAULT_JSON_GENERATOR.)
|
64
64
|
# <tt>:geojson</tt>::
|
65
65
|
# GeoJSON format. Requires the rgeo-geojson gem.
|
66
|
-
|
66
|
+
|
67
67
|
def self.set_json_generator(value_=nil, &block_)
|
68
68
|
if block_ && !value_
|
69
69
|
value_ = block_
|
@@ -77,30 +77,30 @@ module RGeo
|
|
77
77
|
@json_generator = DEFAULT_JSON_GENERATOR
|
78
78
|
end
|
79
79
|
end
|
80
|
-
|
81
|
-
|
80
|
+
|
81
|
+
|
82
82
|
# Given a feature, returns an object that can be serialized as JSON
|
83
83
|
# (i.e. usually a hash or string), using the current json_generator.
|
84
84
|
# This is used to generate JSON for geometry-valued ActiveRecord
|
85
85
|
# fields by default.
|
86
|
-
|
86
|
+
|
87
87
|
def self.generate_json(geom_)
|
88
88
|
@json_generator.call(geom_)
|
89
89
|
end
|
90
|
-
|
91
|
-
|
90
|
+
|
91
|
+
|
92
92
|
# Serializes this object as JSON for ActiveRecord.
|
93
|
-
|
93
|
+
|
94
94
|
def as_json(opts_=nil)
|
95
95
|
GeometryMixin.generate_json(self)
|
96
96
|
end
|
97
|
-
|
98
|
-
|
97
|
+
|
98
|
+
|
99
99
|
end
|
100
|
-
|
101
|
-
|
100
|
+
|
101
|
+
|
102
102
|
end
|
103
|
-
|
103
|
+
|
104
104
|
end
|
105
105
|
|
106
106
|
|