rgeo-activerecord 0.2.0 → 0.2.1

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 CHANGED
@@ -1,3 +1,8 @@
1
+ === 0.2.1 / 2010-12-27
2
+
3
+ * Support for RGeo features as nodes in the Arel AST.
4
+ * Basic utility Arel visitor methods for handling spatial equality nodes in where-expressions.
5
+
1
6
  === 0.2.0 / 2010-12-07
2
7
 
3
8
  * Initial public alpha release. Spun rgeo-activerecord off from the core rgeo gem.
data/README.rdoc CHANGED
@@ -15,14 +15,15 @@ along with a set of geometric analysis operations. See the README for the
15
15
 
16
16
  RGeo::ActiveRecord is an optional \RGeo add-on module providing spatial
17
17
  extensions for \ActiveRecord, as well as a set of helpers for writing
18
- spatial \ActiveRecord adapters based on \RGeo.
18
+ spatial \ActiveRecord adapters based on \RGeo. Generally, you will not
19
+ interact directly with this library
19
20
 
20
21
  === Installation
21
22
 
22
23
  RGeo::ActiveRecord has the following requirements:
23
24
 
24
25
  * Ruby 1.8.7 or later. Ruby 1.9.2 or later preferred.
25
- * \RGeo 0.2.0 or later.
26
+ * \RGeo 0.2.3 or later.
26
27
  * \ActiveRecord 3.0.3 or later. Earlier versions will not work.
27
28
 
28
29
  Generally, \ActiveRecord adapters which depend on this module should be
@@ -37,8 +38,7 @@ installation information.
37
38
 
38
39
  === To-do list
39
40
 
40
- * We want to investigate writing some Arel extensions for constructing
41
- spatial queries.
41
+ * Arel extensions for constructing more complex spatial queries.
42
42
 
43
43
  === Development and support
44
44
 
data/Version CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
@@ -37,14 +37,39 @@
37
37
  require 'arel'
38
38
 
39
39
 
40
- # :stopdoc:
40
+ # The rgeo-activerecord gem installs several hacks into Arel to support
41
+ # geometry values and geometry-valued columns.
42
+ #
43
+ # To support geometry values as nodes in the Arel AST, we need to provide
44
+ # a way for visitors to handle nodes that are feature objects.
45
+ # Generally, this is accomplished by writing (or aliasing) methods in the
46
+ # visitor of the form "visit_<classname>". Arel will dispatch to a method
47
+ # based on the class of the object in the AST. Unfortunately, RGeo feature
48
+ # objects usually have opaque classes; plus, there are so many different
49
+ # classes as to make it infeasible to list all of them. Therefore, we hack
50
+ # Arel::Visitors::Visitor#visit to explicitly recognize the
51
+ # RGeo::Feature::Instance marker module, and we define the method
52
+ # visit_RGeo_Feature_Instance. In the various visitors (Dot, DepthFirst,
53
+ # and ToSql), this method is aliased in the same way as the other raw
54
+ # values. For the ToSql visitor, this means aliasing to visit_String,
55
+ # which then depends on the quoting implemented by the connection adapter
56
+ # to convert to a SQL literal.
57
+ #
58
+ # To support geometry columns, we define Arel::Attributes::Geometry, and
59
+ # we hack Arel::Attributes::for to map the :geometry column type to that
60
+ # new attribute. We then add the appropriate alias for the
61
+ # visit_Arel_Attributes_Geometry method to the visitors.
41
62
 
42
63
  module Arel
43
64
 
65
+ # :stopdoc:
66
+
44
67
  module Attributes
45
68
 
69
+ # New attribute type for geometry-valued column
46
70
  class Geometry < Attribute; end
47
71
 
72
+ # Hack Attributes dispatcher to recognize geometry columns
48
73
  class << self
49
74
  alias_method :for_without_geometry, :for
50
75
  def for(column_)
@@ -56,18 +81,40 @@ module Arel
56
81
 
57
82
  module Visitors
58
83
 
84
+ # Hack visit dispatcher to recognize RGeo features as nodes.
85
+ # We need a special dispatcher code because the default dispatcher
86
+ # triggers on class name. RGeo features tend to have opaque classes.
87
+ class Visitor
88
+ alias_method :visit_without_rgeo_types, :visit
89
+ def visit(object_)
90
+ if object_.kind_of?(::RGeo::Feature::Instance) && respond_to?(:visit_RGeo_Feature_Instance)
91
+ visit_RGeo_Feature_Instance(object_)
92
+ else
93
+ visit_without_rgeo_types(object_)
94
+ end
95
+ end
96
+ end
97
+
98
+ # Dot visitor handlers for geometry attributes and values.
59
99
  class Dot
60
100
  alias :visit_Arel_Attributes_Geometry :visit_Arel_Attribute
61
- alias :visit_RGeo_Feature_Geometry :visit_String
101
+ alias :visit_RGeo_Feature_Instance :visit_String
62
102
  end
63
103
 
104
+ # DepthFirst visitor handlers for geometry attributes and values.
105
+ class DepthFirst
106
+ alias :visit_Arel_Attributes_Geometry :visit_Arel_Attribute
107
+ alias :visit_RGeo_Feature_Instance :terminal
108
+ end
109
+
110
+ # ToSql visitor handlers for geometry attributes and values.
64
111
  class ToSql
65
112
  alias :visit_Arel_Attributes_Geometry :visit_Arel_Attributes_Attribute
66
- alias :visit_RGeo_Feature_Geometry :visit_String
113
+ alias :visit_RGeo_Feature_Instance :visit_String
67
114
  end
68
115
 
69
116
  end
70
117
 
118
+ # :startdoc:
119
+
71
120
  end
72
-
73
- # :startdoc:
@@ -52,6 +52,47 @@ module RGeo
52
52
  end
53
53
 
54
54
 
55
+ # A set of common Arel visitor hacks for spatial ToSql visitors.
56
+
57
+ module SpatialToSql
58
+
59
+ # Map a standard OGC SQL function name to the actual name used by
60
+ # a particular database.
61
+ def st_func(standard_name_)
62
+ standard_name_
63
+ end
64
+
65
+ def visit_Arel_Nodes_Equality(node_) # :nodoc:
66
+ right_ = node_.right
67
+ left_ = node_.left
68
+ if left_.kind_of?(::Arel::Attributes::Geometry)
69
+ case right_
70
+ when ::RGeo::Feature::Instance
71
+ return "#{st_func('ST_Equals')}(#{visit(left_)}, #{visit(right_)})"
72
+ when ::String
73
+ return "#{st_func('ST_Equals')}(#{visit(left_)}, #{st_func('ST_WKTToSQL')}(#{visit(right_)}))"
74
+ end
75
+ end
76
+ super
77
+ end
78
+
79
+ def visit_Arel_Nodes_NotEqual(node_) # :nodoc:
80
+ right_ = node_.right
81
+ left_ = node_.left
82
+ if left_.kind_of?(::Arel::Attributes::Geometry)
83
+ case right_
84
+ when ::RGeo::Feature::Instance
85
+ return "NOT #{st_func('ST_Equals')}(#{visit(left_)}, #{visit(right_)})"
86
+ when ::String
87
+ return "NOT #{st_func('ST_Equals')}(#{visit(left_)}, #{st_func('ST_WKTToSQL')}(#{visit(right_)}))"
88
+ end
89
+ end
90
+ super
91
+ end
92
+
93
+ end
94
+
95
+
55
96
  # Index definition struct with a spatial flag field.
56
97
 
57
98
  class SpatialIndexDefinition < ::Struct.new(:table, :name, :unique, :columns, :lengths, :spatial)
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 0
9
- version: 0.2.0
8
+ - 1
9
+ version: 0.2.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Daniel Azuma
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-12-07 00:00:00 -08:00
17
+ date: 2010-12-27 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -28,8 +28,8 @@ dependencies:
28
28
  segments:
29
29
  - 0
30
30
  - 2
31
- - 0
32
- version: 0.2.0
31
+ - 3
32
+ version: 0.2.3
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency