rgeo-activerecord 0.6.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,44 +1,5 @@
1
- # -----------------------------------------------------------------------------
2
- #
3
- # Various Arel hacks to support spatial queries
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
1
  module RGeo
38
-
39
2
  module ActiveRecord
40
-
41
-
42
3
  # A set of common Arel visitor hacks for spatial ToSql visitors.
43
4
  # Generally, a spatial ActiveRecord adapter should provide a custom
44
5
  # ToSql Arel visitor that includes and customizes this module.
@@ -47,7 +8,6 @@ module RGeo
47
8
 
48
9
  module SpatialToSql
49
10
 
50
-
51
11
  # Map a standard OGC SQL function name to the actual name used by
52
12
  # a particular database. This method should take a name and
53
13
  # return either the changed name or the original name.
@@ -56,7 +16,6 @@ module RGeo
56
16
  standard_name_
57
17
  end
58
18
 
59
-
60
19
  # Visit the SpatialNamedFunction node. This operates similarly to
61
20
  # the standard NamedFunction node, but it performs function name
62
21
  # mapping for the database, and it also uses the type information
@@ -71,11 +30,9 @@ module RGeo
71
30
  "#{name_}(#{node_.distinct ? 'DISTINCT ' : ''}#{exprs_.join(', ')})#{node_.alias ? " AS #{visit(node_.alias, *args)}" : ''}"
72
31
  end
73
32
 
74
-
75
33
  # Generates SQL for a spatial node.
76
34
  # The node must be a string (in which case it is treated as WKT),
77
35
  # an RGeo feature, or a spatial attribute.
78
-
79
36
  def visit_in_spatial_context(node_, *args)
80
37
  case node_
81
38
  when ::String
@@ -88,50 +45,24 @@ module RGeo
88
45
  visit(node_, *args)
89
46
  end
90
47
  end
91
-
92
-
93
48
  end
94
49
 
95
-
96
50
  # This node wraps an RGeo feature and gives it spatial expression
97
51
  # constructors.
98
-
99
52
  class SpatialConstantNode
100
-
101
53
  include ::RGeo::ActiveRecord::SpatialExpressions
102
54
 
103
-
104
55
  # The delegate should be the RGeo feature.
105
-
106
56
  def initialize(delegate_)
107
57
  @delegate = delegate_
108
58
  end
109
59
 
110
-
111
60
  # Return the RGeo feature
112
-
113
61
  attr_reader :delegate
114
-
115
-
116
62
  end
117
63
 
118
-
119
64
  # :stopdoc:
120
65
 
121
-
122
- # Hack Arel Attributes dispatcher to recognize geometry columns.
123
- # This is deprecated but necessary to support legacy Arel versions.
124
-
125
- if ::Arel::Attributes.method_defined?(:for)
126
- module ArelAttributesLegacyClassMethods
127
- def for(column_)
128
- column_.type == :spatial ? Attribute : super
129
- end
130
- end
131
- ::Arel::Attributes.extend(ArelAttributesLegacyClassMethods)
132
- end
133
-
134
-
135
66
  # Make sure the standard Arel visitors can handle RGeo feature objects
136
67
  # by default.
137
68
 
@@ -158,58 +89,29 @@ module RGeo
158
89
  end
159
90
 
160
91
 
161
- # Add tools to build spatial structures in the AST.
162
- # This stuff requires Arel 2.1 or later.
163
-
164
- if defined?(::Arel::Nodes::NamedFunction)
92
+ # A NamedFunction subclass that keeps track of the spatial-ness of
93
+ # the arguments and return values, so that it can provide context to
94
+ # visitors that want to interpret syntax differently when dealing with
95
+ # spatial elements.
96
+ class SpatialNamedFunction < ::Arel::Nodes::NamedFunction
97
+ include ::RGeo::ActiveRecord::SpatialExpressions
165
98
 
166
- # Allow chaining of predications from named functions
167
- # (Some older versions of Arel didn't do this.)
168
- ::Arel::Nodes::NamedFunction.class_eval do
169
- include ::Arel::Predications unless include?(::Arel::Predications)
99
+ def initialize(name_, expr_, spatial_flags_=[], aliaz_=nil)
100
+ super(name_, expr_, aliaz_)
101
+ @spatial_flags = spatial_flags_
170
102
  end
171
103
 
172
- # Allow chaining of spatial expressions from attributes
173
- ::Arel::Attribute.class_eval do
174
- include ::RGeo::ActiveRecord::SpatialExpressions
104
+ def spatial_result?
105
+ @spatial_flags.first
175
106
  end
176
107
 
177
-
178
- # A NamedFunction subclass that keeps track of the spatial-ness of
179
- # the arguments and return values, so that it can provide context to
180
- # visitors that want to interpret syntax differently when dealing with
181
- # spatial elements.
182
-
183
- class SpatialNamedFunction < ::Arel::Nodes::NamedFunction
184
-
185
- include ::RGeo::ActiveRecord::SpatialExpressions
186
-
187
- def initialize(name_, expr_, spatial_flags_=[], aliaz_=nil)
188
- super(name_, expr_, aliaz_)
189
- @spatial_flags = spatial_flags_
190
- end
191
-
192
- def spatial_result?
193
- @spatial_flags.first
194
- end
195
-
196
- def spatial_argument?(index_)
197
- @spatial_flags[index_+1]
198
- end
199
-
108
+ def spatial_argument?(index_)
109
+ @spatial_flags[index_+1]
200
110
  end
201
111
 
202
- else
203
-
204
- # A dummy SpatialNamedFunction for pre-2.1 versions of Arel.
205
- class SpatialNamedFunction; end
206
-
207
112
  end
208
113
 
209
-
210
114
  # :startdoc:
211
115
 
212
-
213
116
  end
214
-
215
117
  end
@@ -1,55 +1,10 @@
1
- # -----------------------------------------------------------------------------
2
- #
3
- # Common tools for spatial adapters for 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
-
36
-
37
- require 'active_support/core_ext/class' # Workaround for a missing require in ActiveRecord 3.2.1
38
- require 'active_record'
39
-
40
- # Force AbstractAdapter to autoload
41
- if ::ActiveRecord::ConnectionAdapters::AbstractAdapter
42
- end
43
-
1
+ # autoload AbstractAdapter
2
+ ::ActiveRecord::ConnectionAdapters::AbstractAdapter
44
3
 
45
4
  module RGeo
46
-
47
5
  module ActiveRecord
48
-
49
-
50
6
  # Some default column constructors specifications for most spatial
51
7
  # databases. Individual adapters may add to or override this list.
52
-
53
8
  DEFAULT_SPATIAL_COLUMN_CONSTRUCTORS = {
54
9
  :spatial => {:type => 'geometry'}.freeze,
55
10
  :geometry => {}.freeze,
@@ -62,13 +17,11 @@ module RGeo
62
17
  :multi_polygon => {}.freeze,
63
18
  }.freeze
64
19
 
65
-
66
20
  # Index definition struct with a spatial flag field.
67
21
 
68
22
  class SpatialIndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :spatial)
69
23
  end
70
24
 
71
-
72
25
  # Returns a feature type module given a string type.
73
26
 
74
27
  def self.geometric_type_from_name(name_)
@@ -85,17 +38,18 @@ module RGeo
85
38
  end
86
39
  end
87
40
 
88
-
89
41
  # :stopdoc:
90
42
 
91
-
92
43
  # Provide methods for each geometric subtype during table definitions.
44
+ module GeoTableDefinitions
45
+ def self.included(base)
46
+ base.class_eval do
47
+ alias_method :method_missing_without_rgeo, :method_missing
48
+ alias_method :method_missing, :method_missing_with_rgeo
49
+ end
50
+ end
93
51
 
94
- ::ActiveRecord::ConnectionAdapters::TableDefinition.class_eval do
95
-
96
- alias_method :method_missing_without_rgeo_modification, :method_missing
97
-
98
- def method_missing(method_name_, *args_, &block_)
52
+ def method_missing_with_rgeo(method_name_, *args_, &block_)
99
53
  if @base.respond_to?(:spatial_column_constructor) && (info_ = @base.spatial_column_constructor(method_name_))
100
54
  info_ = info_.dup
101
55
  type_ = (info_.delete(:type) || method_name_).to_s
@@ -104,20 +58,24 @@ module RGeo
104
58
  column(name_, type_, opts_)
105
59
  end
106
60
  else
107
- method_missing_without_rgeo_modification(method_name_, *args_, &block_)
61
+ method_missing_without_rgeo(method_name_, *args_, &block_)
108
62
  end
109
63
  end
110
-
111
64
  end
112
65
 
66
+ ::ActiveRecord::ConnectionAdapters::TableDefinition.send :include, GeoTableDefinitions
113
67
 
114
- # Provide methods for each geometric subtype during table changes.
115
-
116
- ::ActiveRecord::ConnectionAdapters::Table.class_eval do
117
68
 
118
- alias_method :method_missing_without_rgeo_modification, :method_missing
69
+ # Provide methods for each geometric subtype during table changes.
70
+ module GeoConnectionAdapters
71
+ def self.included(base)
72
+ base.class_eval do
73
+ alias_method :method_missing_without_rgeo, :method_missing
74
+ alias_method :method_missing, :method_missing_with_rgeo
75
+ end
76
+ end
119
77
 
120
- def method_missing(method_name_, *args_, &block_)
78
+ def method_missing_with_rgeo(method_name_, *args_, &block_)
121
79
  if @base.respond_to?(:spatial_column_constructor) && (info_ = @base.spatial_column_constructor(method_name_))
122
80
  info_ = info_.dup
123
81
  type_ = (info_.delete(:type) || method_name_).to_s
@@ -126,22 +84,26 @@ module RGeo
126
84
  @base.add_column(@table_name, name_, type_, opts_)
127
85
  end
128
86
  else
129
- method_missing_without_rgeo_modification(method_name_, *args_, &block_)
87
+ method_missing_without_rgeo(method_name_, *args_, &block_)
130
88
  end
131
89
  end
132
-
133
90
  end
134
91
 
92
+ ::ActiveRecord::ConnectionAdapters::Table.send :include, GeoConnectionAdapters
135
93
 
136
- # Hack schema dumper to output spatial index flag
137
94
 
138
- ::ActiveRecord::SchemaDumper.class_eval do
95
+ # Hack schema dumper to output spatial index flag
96
+ module GeoSchemaDumper
97
+ def self.included(base)
98
+ base.class_eval do
99
+ alias_method :indexes_without_rgeo, :indexes
100
+ alias_method :indexes, :indexes_with_rgeo
101
+ end
102
+ end
139
103
 
140
104
  private
141
105
 
142
- alias_method :_old_indexes_method, :indexes
143
-
144
- def indexes(table_, stream_)
106
+ def indexes_with_rgeo(table_, stream_)
145
107
  if (indexes_ = @connection.indexes(table_)).any?
146
108
  add_index_statements_ = indexes_.map do |index_|
147
109
  statement_parts_ = [
@@ -159,19 +121,15 @@ module RGeo
159
121
  stream_.puts
160
122
  end
161
123
  end
162
-
163
124
  end
164
125
 
126
+ ::ActiveRecord::SchemaDumper.send :include, GeoSchemaDumper
165
127
 
166
- # Tell ActiveRecord to cache spatial attribute values so they don't get
167
- # re-parsed on every access.
168
128
 
169
- ::ActiveRecord::Base.attribute_types_cached_by_default << :spatial
129
+ # Tell ActiveRecord to cache spatial attribute values so they don't get re-parsed on every access.
170
130
 
131
+ ::ActiveRecord::Base.attribute_types_cached_by_default << :spatial
171
132
 
172
133
  # :startdoc:
173
-
174
-
175
134
  end
176
-
177
135
  end
@@ -1,57 +1,15 @@
1
- # -----------------------------------------------------------------------------
2
- #
3
- # Geometry mixin for JSON serialization
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
1
  module RGeo
38
-
39
2
  module ActiveRecord
40
-
41
-
42
3
  # This module is mixed into all geometry objects. It provides an
43
4
  # as_json method so that ActiveRecord knows how to generate JSON
44
5
  # for a geometry-valued field.
45
6
 
46
7
  module GeometryMixin
47
-
48
-
49
8
  # The default JSON generator Proc. Renders geometry fields as WKT.
50
9
  DEFAULT_JSON_GENERATOR = ::Proc.new{ |geom_| geom_.to_s }
51
10
 
52
11
  @json_generator = DEFAULT_JSON_GENERATOR
53
12
 
54
-
55
13
  # Set the style of JSON generation used for geometry fields in an
56
14
  # ActiveRecord model by default. You may pass nil to use
57
15
  # DEFAULT_JSON_GENERATOR, a proc that takes a geometry as the
@@ -78,7 +36,6 @@ module RGeo
78
36
  end
79
37
  end
80
38
 
81
-
82
39
  # Given a feature, returns an object that can be serialized as JSON
83
40
  # (i.e. usually a hash or string), using the current json_generator.
84
41
  # This is used to generate JSON for geometry-valued ActiveRecord
@@ -94,15 +51,9 @@ module RGeo
94
51
  def as_json(opts_=nil)
95
52
  GeometryMixin.generate_json(self)
96
53
  end
97
-
98
-
99
54
  end
100
-
101
-
102
55
  end
103
-
104
56
  end
105
57
 
106
-
107
58
  ::RGeo::Feature::MixinCollection::GLOBAL.for_type(::RGeo::Feature::Geometry).
108
59
  add(::RGeo::ActiveRecord::GeometryMixin)