rgeo-activerecord 1.2.0 → 1.3.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 +4 -4
- data/History.md +5 -0
- data/lib/rgeo/active_record/ar_factory_settings.rb +40 -43
- data/lib/rgeo/active_record/arel_spatial_queries.rb +29 -30
- data/lib/rgeo/active_record/common_adapter_elements.rb +51 -43
- data/lib/rgeo/active_record/geometry_mixin.rb +11 -12
- data/lib/rgeo/active_record/spatial_expressions.rb +55 -55
- data/lib/rgeo/active_record/version.rb +1 -1
- data/test/basic_test.rb +75 -0
- data/test/test_helper.rb +0 -4
- metadata +5 -5
- data/test/tc_basic.rb +0 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11ad920c01d1f944cd3d7f4f658b4138a1954284
|
4
|
+
data.tar.gz: 184abfc52e1c1708726c344bc66842133381949d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bffb41f789ef87f8557cbdbc786a3c2070c7d193e9fe819467397b556a613ac8a9b9e363def43a0f09afcfdfae8fdddeaf4b1584f5166901dbd59be2c6af1f8
|
7
|
+
data.tar.gz: 7254fcac74eb52b88152d27f8f452045f376202462365822432e0cda43c35ffa6f0df65516ad85f63e9f6b9a2af5eabc8d60e25da28bc7f5136b1b28c59745b2
|
data/History.md
CHANGED
@@ -2,11 +2,11 @@ module RGeo
|
|
2
2
|
module ActiveRecord
|
3
3
|
# The default factory generator for ActiveRecord::Base.
|
4
4
|
|
5
|
-
DEFAULT_FACTORY_GENERATOR = ::Proc.new do |
|
6
|
-
if
|
7
|
-
::RGeo::Geographic.spherical_factory(
|
5
|
+
DEFAULT_FACTORY_GENERATOR = ::Proc.new do |config|
|
6
|
+
if config.delete(:geographic)
|
7
|
+
::RGeo::Geographic.spherical_factory(config)
|
8
8
|
else
|
9
|
-
::RGeo::Cartesian.preferred_factory(
|
9
|
+
::RGeo::Cartesian.preferred_factory(config)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -19,40 +19,38 @@ module RGeo
|
|
19
19
|
end
|
20
20
|
|
21
21
|
# Get the default factory generator for the given table
|
22
|
-
def get_factory_generator(
|
23
|
-
@factory_generators[
|
22
|
+
def get_factory_generator(table_name)
|
23
|
+
@factory_generators[table_name.to_s] || ::RGeo::ActiveRecord::DEFAULT_FACTORY_GENERATOR
|
24
24
|
end
|
25
25
|
|
26
26
|
# Set the default factory generator for the given table
|
27
|
-
def set_factory_generator(
|
28
|
-
@factory_generators[
|
27
|
+
def set_factory_generator(table_name, generator)
|
28
|
+
@factory_generators[table_name.to_s] = generator
|
29
29
|
end
|
30
30
|
|
31
|
-
# Get the factory or factory generator for the given table name
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
result_ = result_.call(params_)
|
31
|
+
# Get the factory or factory generator for the given table name and column name.
|
32
|
+
def get_column_factory(table_name, column_name, params = nil)
|
33
|
+
table_name = table_name.to_s
|
34
|
+
column_name = column_name.to_s
|
35
|
+
result = (@column_factories[table_name] ||= {})[column_name] ||
|
36
|
+
@factory_generators[table_name] || ::RGeo::ActiveRecord::DEFAULT_FACTORY_GENERATOR
|
37
|
+
if params && !result.kind_of?(::RGeo::Feature::Factory::Instance)
|
38
|
+
result = result.call(params)
|
40
39
|
end
|
41
|
-
|
40
|
+
result
|
42
41
|
end
|
43
42
|
|
44
|
-
# Set the factory or factory generator for the given table name
|
45
|
-
|
46
|
-
|
47
|
-
(@column_factories[table_name_.to_s] ||= {})[column_name_.to_s] = factory_
|
43
|
+
# Set the factory or factory generator for the given table name and column name.
|
44
|
+
def set_column_factory(table_name, column_name, factory)
|
45
|
+
(@column_factories[table_name.to_s] ||= {})[column_name.to_s] = factory
|
48
46
|
end
|
49
47
|
|
50
48
|
# Clear settings for the given table name, or for all tables
|
51
|
-
def clear!(
|
52
|
-
if
|
53
|
-
|
54
|
-
@factory_generators.delete(
|
55
|
-
@column_factories.delete(
|
49
|
+
def clear!(table_name = nil)
|
50
|
+
if table_name
|
51
|
+
table_name = table_name.to_s
|
52
|
+
@factory_generators.delete(table_name)
|
53
|
+
@column_factories.delete(table_name)
|
56
54
|
else
|
57
55
|
@factory_generators.clear
|
58
56
|
@column_factories.clear
|
@@ -65,15 +63,14 @@ module RGeo
|
|
65
63
|
# Additional class methods on ::ActiveRecord::Base that provide
|
66
64
|
# a way to control the RGeo factory used for ActiveRecord objects.
|
67
65
|
module ActiveRecordBaseFactorySettings
|
68
|
-
# Return the RGeoFactorySettings object associated with this
|
69
|
-
# class's connection.
|
66
|
+
# Return the RGeoFactorySettings object associated with this class's connection.
|
70
67
|
def rgeo_factory_settings
|
71
|
-
|
68
|
+
pool = begin
|
72
69
|
connection_pool
|
73
70
|
rescue ::ActiveRecord::ConnectionNotEstablished
|
74
71
|
nil
|
75
72
|
end
|
76
|
-
|
73
|
+
pool ? pool.rgeo_factory_settings : RGeoFactorySettings::DEFAULT
|
77
74
|
end
|
78
75
|
|
79
76
|
# The value of this attribute is a RGeo::Feature::FactoryGenerator
|
@@ -92,21 +89,21 @@ module RGeo
|
|
92
89
|
end
|
93
90
|
|
94
91
|
# Set the rgeo_factory_generator attribute
|
95
|
-
def rgeo_factory_generator=(
|
96
|
-
rgeo_factory_settings.set_factory_generator(table_name,
|
92
|
+
def rgeo_factory_generator=(generator)
|
93
|
+
rgeo_factory_settings.set_factory_generator(table_name, generator)
|
97
94
|
end
|
98
95
|
|
99
96
|
# This is a convenient way to set the rgeo_factory_generator by
|
100
97
|
# passing a block.
|
101
|
-
def to_generate_rgeo_factory(&
|
102
|
-
rgeo_factory_settings.set_factory_generator(table_name,
|
98
|
+
def to_generate_rgeo_factory(&block)
|
99
|
+
rgeo_factory_settings.set_factory_generator(table_name, block)
|
103
100
|
end
|
104
101
|
|
105
102
|
# Set a specific factory for this ActiveRecord class and the given
|
106
103
|
# column name. This setting, if present, overrides the result of the
|
107
104
|
# rgeo_factory_generator.
|
108
|
-
def set_rgeo_factory_for_column(
|
109
|
-
rgeo_factory_settings.set_column_factory(table_name,
|
105
|
+
def set_rgeo_factory_for_column(column_name, factory)
|
106
|
+
rgeo_factory_settings.set_column_factory(table_name, column_name, factory)
|
110
107
|
end
|
111
108
|
|
112
109
|
# Returns the factory generator or specific factory to use for this
|
@@ -116,8 +113,8 @@ module RGeo
|
|
116
113
|
# rgeo_factory_generator for this class, and returns the resulting
|
117
114
|
# factory. Otherwise, if no params hash is given, just returns the
|
118
115
|
# rgeo_factory_generator for this class.
|
119
|
-
def rgeo_factory_for_column(
|
120
|
-
rgeo_factory_settings.get_column_factory(table_name,
|
116
|
+
def rgeo_factory_for_column(column_name, params = nil)
|
117
|
+
rgeo_factory_settings.get_column_factory(table_name, column_name, params)
|
121
118
|
end
|
122
119
|
end
|
123
120
|
|
@@ -135,11 +132,11 @@ module RGeo
|
|
135
132
|
|
136
133
|
alias_method :new_connection_without_rgeo_modification, :new_connection
|
137
134
|
def new_connection
|
138
|
-
|
139
|
-
if
|
140
|
-
|
135
|
+
result = new_connection_without_rgeo_modification
|
136
|
+
if result.respond_to?(:set_rgeo_factory_settings)
|
137
|
+
result.set_rgeo_factory_settings(rgeo_factory_settings)
|
141
138
|
end
|
142
|
-
|
139
|
+
result
|
143
140
|
end
|
144
141
|
end
|
145
142
|
|
@@ -12,8 +12,8 @@ module RGeo
|
|
12
12
|
# a particular database. This method should take a name and
|
13
13
|
# return either the changed name or the original name.
|
14
14
|
|
15
|
-
def st_func(
|
16
|
-
|
15
|
+
def st_func(standard_name)
|
16
|
+
standard_name
|
17
17
|
end
|
18
18
|
|
19
19
|
# Visit the SpatialNamedFunction node. This operates similarly to
|
@@ -21,40 +21,39 @@ module RGeo
|
|
21
21
|
# mapping for the database, and it also uses the type information
|
22
22
|
# in the node to determine when to cast string arguments to WKT,
|
23
23
|
|
24
|
-
def visit_RGeo_ActiveRecord_SpatialNamedFunction(
|
25
|
-
name_ = st_func(
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
def visit_RGeo_ActiveRecord_SpatialNamedFunction(node, *args)
|
25
|
+
name_ = st_func(node.name)
|
26
|
+
exprs = []
|
27
|
+
node.expressions.each_with_index do |expr, index|
|
28
|
+
exprs << (node.spatial_argument?(index) ? visit_in_spatial_context(expr, *args) : visit(expr, *args))
|
29
29
|
end
|
30
|
-
"#{name_}(#{
|
30
|
+
"#{name_}(#{node.distinct ? 'DISTINCT ' : ''}#{exprs.join(', ')})#{node.alias ? " AS #{visit(node.alias, *args)}" : ''}"
|
31
31
|
end
|
32
32
|
|
33
33
|
# Generates SQL for a spatial node.
|
34
34
|
# The node must be a string (in which case it is treated as WKT),
|
35
35
|
# an RGeo feature, or a spatial attribute.
|
36
|
-
def visit_in_spatial_context(
|
37
|
-
case
|
36
|
+
def visit_in_spatial_context(node, *args)
|
37
|
+
case node
|
38
38
|
when ::String
|
39
|
-
"#{st_func('ST_WKTToSQL')}(#{quote(
|
39
|
+
"#{st_func('ST_WKTToSQL')}(#{quote(node)})"
|
40
40
|
when ::RGeo::Feature::Instance
|
41
|
-
visit_RGeo_Feature_Instance(
|
41
|
+
visit_RGeo_Feature_Instance(node, *args)
|
42
42
|
when ::RGeo::Cartesian::BoundingBox
|
43
|
-
visit_RGeo_Cartesian_BoundingBox(
|
43
|
+
visit_RGeo_Cartesian_BoundingBox(node, *args)
|
44
44
|
else
|
45
|
-
visit(
|
45
|
+
visit(node, *args)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
# This node wraps an RGeo feature and gives it spatial expression
|
51
|
-
# constructors.
|
50
|
+
# This node wraps an RGeo feature and gives it spatial expression constructors.
|
52
51
|
class SpatialConstantNode
|
53
52
|
include ::RGeo::ActiveRecord::SpatialExpressions
|
54
53
|
|
55
54
|
# The delegate should be the RGeo feature.
|
56
|
-
def initialize(
|
57
|
-
@delegate =
|
55
|
+
def initialize(delegate)
|
56
|
+
@delegate = delegate
|
58
57
|
end
|
59
58
|
|
60
59
|
# Return the RGeo feature
|
@@ -63,32 +62,33 @@ module RGeo
|
|
63
62
|
|
64
63
|
# :stopdoc:
|
65
64
|
|
66
|
-
# Make sure the standard Arel visitors can handle RGeo feature objects
|
67
|
-
# by default.
|
65
|
+
# Make sure the standard Arel visitors can handle RGeo feature objects by default.
|
68
66
|
|
69
67
|
::Arel::Visitors::Visitor.class_eval do
|
70
|
-
def visit_RGeo_ActiveRecord_SpatialConstantNode(
|
68
|
+
def visit_RGeo_ActiveRecord_SpatialConstantNode(node, *args)
|
71
69
|
if respond_to?(:visit_in_spatial_context)
|
72
|
-
visit_in_spatial_context(
|
70
|
+
visit_in_spatial_context(node.delegate, *args)
|
73
71
|
else
|
74
|
-
visit(
|
72
|
+
visit(node.delegate, *args)
|
75
73
|
end
|
76
74
|
end
|
77
75
|
end
|
76
|
+
|
78
77
|
::Arel::Visitors::Dot.class_eval do
|
79
78
|
alias :visit_RGeo_Feature_Instance :visit_String
|
80
79
|
alias :visit_RGeo_Cartesian_BoundingBox :visit_String
|
81
80
|
end
|
81
|
+
|
82
82
|
::Arel::Visitors::DepthFirst.class_eval do
|
83
83
|
alias :visit_RGeo_Feature_Instance :terminal
|
84
84
|
alias :visit_RGeo_Cartesian_BoundingBox :terminal
|
85
85
|
end
|
86
|
+
|
86
87
|
::Arel::Visitors::ToSql.class_eval do
|
87
88
|
alias :visit_RGeo_Feature_Instance :visit_String
|
88
89
|
alias :visit_RGeo_Cartesian_BoundingBox :visit_String
|
89
90
|
end
|
90
91
|
|
91
|
-
|
92
92
|
# A NamedFunction subclass that keeps track of the spatial-ness of
|
93
93
|
# the arguments and return values, so that it can provide context to
|
94
94
|
# visitors that want to interpret syntax differently when dealing with
|
@@ -96,19 +96,18 @@ module RGeo
|
|
96
96
|
class SpatialNamedFunction < ::Arel::Nodes::NamedFunction
|
97
97
|
include ::RGeo::ActiveRecord::SpatialExpressions
|
98
98
|
|
99
|
-
def initialize(
|
100
|
-
super(
|
101
|
-
@spatial_flags =
|
99
|
+
def initialize(name, expr, spatial_flags = [], aliaz = nil)
|
100
|
+
super(name, expr, aliaz)
|
101
|
+
@spatial_flags = spatial_flags
|
102
102
|
end
|
103
103
|
|
104
104
|
def spatial_result?
|
105
105
|
@spatial_flags.first
|
106
106
|
end
|
107
107
|
|
108
|
-
def spatial_argument?(
|
109
|
-
@spatial_flags[
|
108
|
+
def spatial_argument?(index)
|
109
|
+
@spatial_flags[index + 1]
|
110
110
|
end
|
111
|
-
|
112
111
|
end
|
113
112
|
|
114
113
|
# :startdoc:
|
@@ -6,26 +6,26 @@ module RGeo
|
|
6
6
|
# Some default column constructors specifications for most spatial
|
7
7
|
# databases. Individual adapters may add to or override this list.
|
8
8
|
DEFAULT_SPATIAL_COLUMN_CONSTRUCTORS = {
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
9
|
+
spatial: { type: 'geometry' }.freeze,
|
10
|
+
geometry: {}.freeze,
|
11
|
+
point: {}.freeze,
|
12
|
+
line_string: {}.freeze,
|
13
|
+
polygon: {}.freeze,
|
14
|
+
geometry_collection: {}.freeze,
|
15
|
+
multi_line_string: {}.freeze,
|
16
|
+
multi_point: {}.freeze,
|
17
|
+
multi_polygon: {}.freeze,
|
18
18
|
}.freeze
|
19
19
|
|
20
20
|
# Index definition struct with a spatial flag field.
|
21
21
|
|
22
|
-
class SpatialIndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :spatial)
|
22
|
+
class SpatialIndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :using, :type, :spatial)
|
23
23
|
end
|
24
24
|
|
25
25
|
# Returns a feature type module given a string type.
|
26
26
|
|
27
|
-
def self.geometric_type_from_name(
|
28
|
-
case
|
27
|
+
def self.geometric_type_from_name(name)
|
28
|
+
case name.to_s
|
29
29
|
when /^geometry/i then ::RGeo::Feature::Geometry
|
30
30
|
when /^point/i then ::RGeo::Feature::Point
|
31
31
|
when /^linestring/i then ::RGeo::Feature::LineString
|
@@ -49,16 +49,16 @@ module RGeo
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
def method_missing_with_rgeo(
|
53
|
-
if @base.respond_to?(:spatial_column_constructor) && (
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
column(
|
52
|
+
def method_missing_with_rgeo(method_name, *args, &block)
|
53
|
+
if @base.respond_to?(:spatial_column_constructor) && (info = @base.spatial_column_constructor(method_name))
|
54
|
+
info = info.dup
|
55
|
+
type = (info.delete(:type) || method_name).to_s
|
56
|
+
opts = args.extract_options!.merge(info)
|
57
|
+
args.each do |name|
|
58
|
+
column(name, type, opts)
|
59
59
|
end
|
60
60
|
else
|
61
|
-
method_missing_without_rgeo(
|
61
|
+
method_missing_without_rgeo(method_name, *args, &block)
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
@@ -75,16 +75,16 @@ module RGeo
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def method_missing_with_rgeo(
|
79
|
-
if @base.respond_to?(:
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
@base.add_column(@table_name,
|
78
|
+
def method_missing_with_rgeo(method_name, *args, &block)
|
79
|
+
if @base.respond_to?(:spatial_column_construcor) && (info = @base.spatial_column_constructor(method_name))
|
80
|
+
info = info.dup
|
81
|
+
type = (info.delete(:type) || method_name).to_s
|
82
|
+
opts = args.extract_options!.merge(info)
|
83
|
+
args.each do |name|
|
84
|
+
@base.add_column(@table_name, name, type, opts)
|
85
85
|
end
|
86
86
|
else
|
87
|
-
method_missing_without_rgeo(
|
87
|
+
method_missing_without_rgeo(method_name, *args, &block)
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|
@@ -103,22 +103,30 @@ module RGeo
|
|
103
103
|
|
104
104
|
private
|
105
105
|
|
106
|
-
def indexes_with_rgeo(
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
106
|
+
def indexes_with_rgeo(table, stream)
|
107
|
+
indexes = @connection.indexes(table)
|
108
|
+
if indexes.any?
|
109
|
+
add_index_statements = indexes.map do |index|
|
110
|
+
statement = [
|
111
|
+
("add_index #{index.table.inspect}"),
|
112
|
+
index.columns.inspect,
|
113
|
+
("name: #{index.name.inspect}"),
|
114
|
+
]
|
115
|
+
statement << 'unique: true' if index.unique
|
116
|
+
statement << 'spatial: true' if index.respond_to?(:spatial) && index.spatial
|
117
|
+
index_lengths = (index.lengths || []).compact
|
118
|
+
statement << ("length: #{::Hash[*index.columns.zip(index.lengths).flatten].inspect}") if index_lengths.any?
|
119
|
+
|
120
|
+
index_orders = index.orders || {}
|
121
|
+
statement << "order: #{index.orders.inspect}" if index_orders.any?
|
122
|
+
statement << "where: #{index.where.inspect}" if index.where
|
123
|
+
statement << "using: #{index.using.inspect}" if index.using
|
124
|
+
statement << "type: #{index.type.inspect}" if index.type
|
125
|
+
|
126
|
+
" #{statement.join(', ')}"
|
119
127
|
end
|
120
|
-
|
121
|
-
|
128
|
+
stream.puts add_index_statements.sort.join("\n")
|
129
|
+
stream.puts
|
122
130
|
end
|
123
131
|
end
|
124
132
|
end
|
@@ -6,7 +6,7 @@ module RGeo
|
|
6
6
|
|
7
7
|
module GeometryMixin
|
8
8
|
# The default JSON generator Proc. Renders geometry fields as WKT.
|
9
|
-
DEFAULT_JSON_GENERATOR = ::Proc.new{ |
|
9
|
+
DEFAULT_JSON_GENERATOR = ::Proc.new{ |geom| geom.to_s }
|
10
10
|
|
11
11
|
@json_generator = DEFAULT_JSON_GENERATOR
|
12
12
|
|
@@ -22,15 +22,15 @@ module RGeo
|
|
22
22
|
# <tt>:geojson</tt>::
|
23
23
|
# GeoJSON format. Requires the rgeo-geojson gem.
|
24
24
|
|
25
|
-
def self.set_json_generator(
|
26
|
-
if
|
27
|
-
|
28
|
-
elsif
|
25
|
+
def self.set_json_generator(value = nil, &block)
|
26
|
+
if block && !value
|
27
|
+
value = block
|
28
|
+
elsif value == :geojson
|
29
29
|
require 'rgeo/geo_json'
|
30
|
-
|
30
|
+
value = ::Proc.new{ |geom_| ::RGeo::GeoJSON.encode(geom_) }
|
31
31
|
end
|
32
|
-
if
|
33
|
-
@json_generator =
|
32
|
+
if value.is_a?(::Proc)
|
33
|
+
@json_generator = value
|
34
34
|
else
|
35
35
|
@json_generator = DEFAULT_JSON_GENERATOR
|
36
36
|
end
|
@@ -41,14 +41,13 @@ module RGeo
|
|
41
41
|
# This is used to generate JSON for geometry-valued ActiveRecord
|
42
42
|
# fields by default.
|
43
43
|
|
44
|
-
def self.generate_json(
|
45
|
-
@json_generator.call(
|
44
|
+
def self.generate_json(geom)
|
45
|
+
@json_generator.call(geom)
|
46
46
|
end
|
47
47
|
|
48
|
-
|
49
48
|
# Serializes this object as JSON for ActiveRecord.
|
50
49
|
|
51
|
-
def as_json(
|
50
|
+
def as_json(opts = nil)
|
52
51
|
GeometryMixin.generate_json(self)
|
53
52
|
end
|
54
53
|
end
|
@@ -18,9 +18,9 @@ module RGeo
|
|
18
18
|
# Generic functions
|
19
19
|
#++
|
20
20
|
|
21
|
-
def st_function(
|
22
|
-
|
23
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new(
|
21
|
+
def st_function(function, *args)
|
22
|
+
spatial_info = args.last.is_a?(::Array) ? args.pop : []
|
23
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new(function, [self] + args, spatial_info)
|
24
24
|
end
|
25
25
|
|
26
26
|
#--
|
@@ -63,70 +63,70 @@ module RGeo
|
|
63
63
|
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Envelope', [self], [true, true])
|
64
64
|
end
|
65
65
|
|
66
|
-
def st_equals(
|
67
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Equals', [self,
|
66
|
+
def st_equals(rhs)
|
67
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Equals', [self, rhs], [false, true, true])
|
68
68
|
end
|
69
69
|
|
70
|
-
def st_disjoint(
|
71
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Disjoint', [self,
|
70
|
+
def st_disjoint(rhs)
|
71
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Disjoint', [self, rhs], [false, true, true])
|
72
72
|
end
|
73
73
|
|
74
|
-
def st_intersects(
|
75
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Intersects', [self,
|
74
|
+
def st_intersects(rhs)
|
75
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Intersects', [self, rhs], [false, true, true])
|
76
76
|
end
|
77
77
|
|
78
|
-
def st_touches(
|
79
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Touches', [self,
|
78
|
+
def st_touches(rhs)
|
79
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Touches', [self, rhs], [false, true, true])
|
80
80
|
end
|
81
81
|
|
82
|
-
def st_crosses(
|
83
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Crosses', [self,
|
82
|
+
def st_crosses(rhs)
|
83
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Crosses', [self, rhs], [false, true, true])
|
84
84
|
end
|
85
85
|
|
86
|
-
def st_within(
|
87
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Within', [self,
|
86
|
+
def st_within(rhs)
|
87
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Within', [self, rhs], [false, true, true])
|
88
88
|
end
|
89
89
|
|
90
|
-
def st_contains(
|
91
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Contains', [self,
|
90
|
+
def st_contains(rhs)
|
91
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Contains', [self, rhs], [false, true, true])
|
92
92
|
end
|
93
93
|
|
94
|
-
def st_overlaps(
|
95
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Overlaps', [self,
|
94
|
+
def st_overlaps(rhs)
|
95
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Overlaps', [self, rhs], [false, true, true])
|
96
96
|
end
|
97
97
|
|
98
|
-
def st_relate(
|
99
|
-
|
100
|
-
|
101
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Relate',
|
98
|
+
def st_relate(rhs, matrix = nil)
|
99
|
+
args = [self, rhs]
|
100
|
+
args << matrix.to_s if matrix
|
101
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Relate', args, [false, true, true, false])
|
102
102
|
end
|
103
103
|
|
104
|
-
def st_distance(
|
105
|
-
|
106
|
-
|
107
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Distance',
|
104
|
+
def st_distance(rhs, units = nil)
|
105
|
+
args = [self, rhs]
|
106
|
+
args << units.to_s if units
|
107
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Distance', args, [false, true, true, false])
|
108
108
|
end
|
109
109
|
|
110
|
-
def st_intersection(
|
111
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Intersection', [self,
|
110
|
+
def st_intersection(rhs)
|
111
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Intersection', [self, rhs], [true, true, true])
|
112
112
|
end
|
113
113
|
|
114
|
-
def st_difference(
|
115
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Difference', [self,
|
114
|
+
def st_difference(rhs)
|
115
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Difference', [self, rhs], [true, true, true])
|
116
116
|
end
|
117
117
|
|
118
|
-
def st_union(
|
119
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Union', [self,
|
118
|
+
def st_union(rhs)
|
119
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Union', [self, rhs], [true, true, true])
|
120
120
|
end
|
121
121
|
|
122
|
-
def st_symdifference(
|
123
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_SymDifference', [self,
|
122
|
+
def st_symdifference(rhs)
|
123
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_SymDifference', [self, rhs], [true, true, true])
|
124
124
|
end
|
125
125
|
|
126
|
-
def st_buffer(
|
127
|
-
|
128
|
-
|
129
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Buffer',
|
126
|
+
def st_buffer(distance, units = nil)
|
127
|
+
args = [self, distance.to_f]
|
128
|
+
args << units.to_s if units
|
129
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Buffer', args, [true, true, false])
|
130
130
|
end
|
131
131
|
|
132
132
|
def st_convexhull
|
@@ -175,10 +175,10 @@ module RGeo
|
|
175
175
|
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_IsRing', [self], [false, true])
|
176
176
|
end
|
177
177
|
|
178
|
-
def st_length(
|
179
|
-
|
180
|
-
|
181
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Length',
|
178
|
+
def st_length(units = nil)
|
179
|
+
args = [self]
|
180
|
+
args << units.to_s if units
|
181
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_Length', args, [false, true, false])
|
182
182
|
end
|
183
183
|
|
184
184
|
|
@@ -190,8 +190,8 @@ module RGeo
|
|
190
190
|
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_NumPoints', [self], [false, true])
|
191
191
|
end
|
192
192
|
|
193
|
-
def st_pointn(
|
194
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_PointN', [self,
|
193
|
+
def st_pointn(n)
|
194
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_PointN', [self, n.to_i], [true, true, false])
|
195
195
|
end
|
196
196
|
|
197
197
|
|
@@ -199,10 +199,10 @@ module RGeo
|
|
199
199
|
# Surface functions
|
200
200
|
#++
|
201
201
|
|
202
|
-
def st_area(
|
203
|
-
|
204
|
-
|
205
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_StartPoint',
|
202
|
+
def st_area(units = nil)
|
203
|
+
args = [self]
|
204
|
+
args << units.to_s if units
|
205
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_StartPoint', args, [false, true, false])
|
206
206
|
end
|
207
207
|
|
208
208
|
def st_centroid
|
@@ -227,8 +227,8 @@ module RGeo
|
|
227
227
|
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_NumInteriorRing', [self], [false, true])
|
228
228
|
end
|
229
229
|
|
230
|
-
def st_interiorringn(
|
231
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_InteriorRingN', [self,
|
230
|
+
def st_interiorringn(n)
|
231
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_InteriorRingN', [self, n.to_i], [true, true, false])
|
232
232
|
end
|
233
233
|
|
234
234
|
#--
|
@@ -239,8 +239,8 @@ module RGeo
|
|
239
239
|
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_NumGeometries', [self], [false, true])
|
240
240
|
end
|
241
241
|
|
242
|
-
def st_geometryn(
|
243
|
-
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_GeometryN', [self,
|
242
|
+
def st_geometryn(n)
|
243
|
+
::RGeo::ActiveRecord::SpatialNamedFunction.new('ST_GeometryN', [self, n.to_i], [true, true, false])
|
244
244
|
end
|
245
245
|
|
246
246
|
end
|
@@ -263,8 +263,8 @@ module Arel
|
|
263
263
|
#
|
264
264
|
# Requires Arel 2.1 or later.
|
265
265
|
|
266
|
-
def self.spatial(
|
267
|
-
::RGeo::ActiveRecord::SpatialConstantNode.new(
|
266
|
+
def self.spatial(arg)
|
267
|
+
::RGeo::ActiveRecord::SpatialConstantNode.new(arg)
|
268
268
|
end
|
269
269
|
|
270
270
|
end
|
data/test/basic_test.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class BasicTest < MINITEST_CLASS # :nodoc:
|
4
|
+
class MyTable < ::ActiveRecord::Base
|
5
|
+
end
|
6
|
+
|
7
|
+
def test_has_version
|
8
|
+
assert RGeo::ActiveRecord::VERSION
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_default_factory_generator
|
12
|
+
MyTable.rgeo_factory_generator = nil
|
13
|
+
factory = MyTable.rgeo_factory_for_column(:hello).call(has_z_coordinate: true, srid: 4326)
|
14
|
+
assert_equal true, factory.property(:has_z_coordinate)
|
15
|
+
assert_equal true, factory.property(:is_cartesian)
|
16
|
+
assert_nil factory.property(:is_geographic)
|
17
|
+
assert_equal 4326, factory.srid
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_set_factory_generator
|
21
|
+
MyTable.rgeo_factory_generator = RGeo::Geographic.method(:spherical_factory)
|
22
|
+
factory = MyTable.rgeo_factory_for_column(:hello, has_z_coordinate: true, srid: 4326)
|
23
|
+
assert_equal true, factory.property(:has_z_coordinate)
|
24
|
+
assert_equal true, factory.property(:is_geographic)
|
25
|
+
assert_nil factory.property(:is_cartesian)
|
26
|
+
assert_equal false, factory.has_projection?
|
27
|
+
assert_equal 4326, factory.srid
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_specific_factory_for_column
|
31
|
+
MyTable.rgeo_factory_generator = nil
|
32
|
+
MyTable.set_rgeo_factory_for_column(:foo, RGeo::Geographic.simple_mercator_factory(has_z_coordinate: true))
|
33
|
+
factory = MyTable.rgeo_factory_for_column(:foo)
|
34
|
+
assert_equal true, factory.property(:has_z_coordinate)
|
35
|
+
assert_equal true, factory.property(:is_geographic)
|
36
|
+
assert_nil factory.property(:is_cartesian)
|
37
|
+
assert_equal true, factory.has_projection?
|
38
|
+
assert_equal 4326, factory.srid
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_default_as_json_wkt
|
42
|
+
RGeo::ActiveRecord::GeometryMixin.set_json_generator(nil)
|
43
|
+
factory = RGeo::Cartesian.preferred_factory
|
44
|
+
point = factory.point(1, 2)
|
45
|
+
assert_equal "POINT (1.0 2.0)", point.as_json
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_default_as_json_geojson
|
49
|
+
RGeo::ActiveRecord::GeometryMixin.set_json_generator(:geojson)
|
50
|
+
factory = RGeo::Cartesian.preferred_factory
|
51
|
+
point = factory.point(1, 2)
|
52
|
+
assert_equal({'type' => 'Point', 'coordinates' => [1.0, 2.0]}, point.as_json)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_arel_visit_spatial_constant_node
|
56
|
+
visitor = arel_visitor
|
57
|
+
|
58
|
+
# :accept API changed in Arel 6.0:
|
59
|
+
# https://github.com/rails/arel/commit/fcd11dcb99d69d
|
60
|
+
sql = if Arel::VERSION > "6.0.0"
|
61
|
+
visitor.accept(Arel.spatial('POINT (1.0 2.0)'), Arel::Collectors::PlainString.new)
|
62
|
+
else
|
63
|
+
visitor.accept(Arel.spatial('POINT (1.0 2.0)'))
|
64
|
+
end
|
65
|
+
|
66
|
+
assert_equal("ST_WKTToSQL('POINT (1.0 2.0)')", sql)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def arel_visitor
|
72
|
+
Arel::Visitors::PostgreSQL.new(Arel::Table.engine.connection)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -10,7 +10,3 @@ MINITEST_CLASS = if defined?(::Minitest::Test)
|
|
10
10
|
|
11
11
|
Arel::Visitors::PostgreSQL.send(:include, ::RGeo::ActiveRecord::SpatialToSql)
|
12
12
|
Arel::Table.engine = FakeRecord::Base.new
|
13
|
-
|
14
|
-
def arel_visitor
|
15
|
-
Arel::Visitors::PostgreSQL.new(Arel::Table.engine.connection)
|
16
|
-
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rgeo-activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Azuma
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rgeo
|
@@ -86,8 +86,8 @@ files:
|
|
86
86
|
- lib/rgeo/active_record/geometry_mixin.rb
|
87
87
|
- lib/rgeo/active_record/spatial_expressions.rb
|
88
88
|
- lib/rgeo/active_record/version.rb
|
89
|
+
- test/basic_test.rb
|
89
90
|
- test/support/fake_record.rb
|
90
|
-
- test/tc_basic.rb
|
91
91
|
- test/test_helper.rb
|
92
92
|
homepage: http://github.com/rgeo/rgeo-activerecord
|
93
93
|
licenses: []
|
@@ -108,12 +108,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
108
|
version: '0'
|
109
109
|
requirements: []
|
110
110
|
rubyforge_project:
|
111
|
-
rubygems_version: 2.
|
111
|
+
rubygems_version: 2.6.12
|
112
112
|
signing_key:
|
113
113
|
specification_version: 4
|
114
114
|
summary: An RGeo module providing spatial extensions to ActiveRecord.
|
115
115
|
test_files:
|
116
|
+
- test/basic_test.rb
|
116
117
|
- test/support/fake_record.rb
|
117
|
-
- test/tc_basic.rb
|
118
118
|
- test/test_helper.rb
|
119
119
|
has_rdoc:
|
data/test/tc_basic.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
module RGeo
|
4
|
-
module ActiveRecord
|
5
|
-
module Tests # :nodoc:
|
6
|
-
class TestBasic < MINITEST_CLASS # :nodoc:
|
7
|
-
class MyTable < ::ActiveRecord::Base
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_has_version
|
11
|
-
assert ::RGeo::ActiveRecord::VERSION
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_default_factory_generator
|
15
|
-
MyTable.rgeo_factory_generator = nil
|
16
|
-
factory_ = MyTable.rgeo_factory_for_column(:hello).call(:has_z_coordinate => true, :srid => 4326)
|
17
|
-
assert_equal(true, factory_.property(:has_z_coordinate))
|
18
|
-
assert_equal(true, factory_.property(:is_cartesian))
|
19
|
-
assert_nil(factory_.property(:is_geographic))
|
20
|
-
assert_equal(4326, factory_.srid)
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_set_factory_generator
|
24
|
-
MyTable.rgeo_factory_generator = ::RGeo::Geographic.method(:spherical_factory)
|
25
|
-
factory_ = MyTable.rgeo_factory_for_column(:hello, :has_z_coordinate => true, :srid => 4326)
|
26
|
-
assert_equal(true, factory_.property(:has_z_coordinate))
|
27
|
-
assert_equal(true, factory_.property(:is_geographic))
|
28
|
-
assert_nil(factory_.property(:is_cartesian))
|
29
|
-
assert_equal(false, factory_.has_projection?)
|
30
|
-
assert_equal(4326, factory_.srid)
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_specific_factory_for_column
|
34
|
-
MyTable.rgeo_factory_generator = nil
|
35
|
-
MyTable.set_rgeo_factory_for_column(:foo, ::RGeo::Geographic.simple_mercator_factory(:has_z_coordinate => true))
|
36
|
-
factory_ = MyTable.rgeo_factory_for_column(:foo)
|
37
|
-
assert_equal(true, factory_.property(:has_z_coordinate))
|
38
|
-
assert_equal(true, factory_.property(:is_geographic))
|
39
|
-
assert_nil(factory_.property(:is_cartesian))
|
40
|
-
assert_equal(true, factory_.has_projection?)
|
41
|
-
assert_equal(4326, factory_.srid)
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_default_as_json_wkt
|
45
|
-
GeometryMixin.set_json_generator(nil)
|
46
|
-
factory_ = ::RGeo::Cartesian.preferred_factory
|
47
|
-
p_ = factory_.point(1, 2)
|
48
|
-
assert_equal("POINT (1.0 2.0)", p_.as_json)
|
49
|
-
end
|
50
|
-
|
51
|
-
def test_default_as_json_geojson
|
52
|
-
GeometryMixin.set_json_generator(:geojson)
|
53
|
-
factory_ = ::RGeo::Cartesian.preferred_factory
|
54
|
-
p_ = factory_.point(1, 2)
|
55
|
-
assert_equal({'type' => 'Point', 'coordinates' => [1.0, 2.0]}, p_.as_json)
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_arel_visit_SpatialConstantNode
|
59
|
-
visitor = arel_visitor
|
60
|
-
|
61
|
-
# :accept API changed in Arel 6.0:
|
62
|
-
# https://github.com/rails/arel/commit/fcd11dcb99d69d
|
63
|
-
sql = if Arel::VERSION > "6.0.0"
|
64
|
-
visitor.accept(Arel.spatial('POINT (1.0 2.0)'), Arel::Collectors::PlainString.new)
|
65
|
-
else
|
66
|
-
visitor.accept(Arel.spatial('POINT (1.0 2.0)'))
|
67
|
-
end
|
68
|
-
|
69
|
-
assert_equal("ST_WKTToSQL('POINT (1.0 2.0)')", sql)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|