rgeo-activerecord 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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