activerecord-mysqlspatial-adapter 0.2.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.
- data/History.rdoc +6 -0
- data/README.rdoc +146 -0
- data/Version +1 -0
- data/lib/active_record/connection_adapters/mysqlspatial_adapter.rb +234 -0
- data/test/tc_basic.rb +171 -0
- metadata +100 -0
data/History.rdoc
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
== MySQL Spatial \ActiveRecord Adapter
|
2
|
+
|
3
|
+
The MySQL Spatial \ActiveRecord Adapter is an \ActiveRecord connection
|
4
|
+
adapter based on the standard mysql adapter. It extends the standard
|
5
|
+
adapter to provide support for spatial columns and indexes in MySQL,
|
6
|
+
using the {RGeo}[http://github.com/dazuma/rgeo] library to represent
|
7
|
+
spatial data in Ruby. Like the standard mysql adapter, this adapter
|
8
|
+
requires the mysql gem.
|
9
|
+
|
10
|
+
=== Usage
|
11
|
+
|
12
|
+
To use this adapter, add this gem, "activerecord-mysqlspatial-adapter",
|
13
|
+
to your Gemfile, and then request the adapter name "mysqlspatial" in
|
14
|
+
your database connection configuration (which, for a Rails application,
|
15
|
+
is in the config/database.yml file). The other database connection
|
16
|
+
configuration parameters are the same as for the stock mysql adapter.
|
17
|
+
|
18
|
+
First, this adapter extends the migration syntax to support creating
|
19
|
+
spatial columns and indexes. To create a spatial column, use the
|
20
|
+
<tt>:geometry</tt> type, or any of the OGC spatial types such as
|
21
|
+
<tt>:point</tt> or <tt>:line_string</tt>. To create a spatial index, set
|
22
|
+
the <tt>:spatial</tt> option to true. Remember that, on some versions of
|
23
|
+
MySQL, only the MyISAM engine supports spatial indexes, and the indexed
|
24
|
+
column may need to be NOT NULL.
|
25
|
+
|
26
|
+
Examples:
|
27
|
+
|
28
|
+
create_table :spatial_table, :options => 'ENGINE=MyISAM' do |t|
|
29
|
+
t.column :latlon, :point, :null => false
|
30
|
+
t.line_string :path
|
31
|
+
t.geometry :shape
|
32
|
+
end
|
33
|
+
change_table :spatial_table do |t|
|
34
|
+
t.index :latlon, :spatial => true
|
35
|
+
end
|
36
|
+
|
37
|
+
When this adapter is in use, spatial attributes in your \ActiveRecord
|
38
|
+
objects will have RGeo geometry values. You can set spatial attributes
|
39
|
+
either to RGeo geometry objects, or to strings in WKT (well-known text)
|
40
|
+
format, which the adapter will automatically convert to geometry objects.
|
41
|
+
|
42
|
+
To specify the RGeo geometry factory, you can either set an explicit
|
43
|
+
factory for a column, or provide a factory generator that will yield the
|
44
|
+
appropriate factory for the table's spatial columns based on the value.
|
45
|
+
For the former, call the set_rgeo_factory_for_column class method on your
|
46
|
+
\ActiveRecord class. For the latter, set the rgeo_factory_generator class
|
47
|
+
attribute. This generator should understand at least the <tt>:srid</tt>
|
48
|
+
options, which will be provided based on the SRID embedded in the value
|
49
|
+
itself, since MySQL does not support SRID or dimension constraints on
|
50
|
+
spatial columns themselves. The set_rgeo_factory_for_column and
|
51
|
+
rgeo_factory_generator methods are actually implemented and documented in
|
52
|
+
the "rgeo-activerecord" gem.
|
53
|
+
|
54
|
+
Examples, given the spatial table defined above:
|
55
|
+
|
56
|
+
class SpatialTable < ActiveRecord::Base
|
57
|
+
|
58
|
+
# By default, use the GEOS implementation for spatial columns.
|
59
|
+
self.rgeo_factory_generator = RGeo::Geos.method(:factory)
|
60
|
+
|
61
|
+
# But use a geographic implementation for the :latlon column.
|
62
|
+
set_rgeo_factory_for_column(:latlon, RGeo::Geographic.spherical_factory)
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
Now you can interact with the data using the RGeo types:
|
67
|
+
|
68
|
+
rec = SpatialTable.new
|
69
|
+
rec.latlon = 'POINT(-122 47)' # You can set by feature object or WKT.
|
70
|
+
loc = rec.latlon # Accessing always returns a feature object, in
|
71
|
+
# this case, a geographic that understands latitude.
|
72
|
+
loc.latitude # => 47
|
73
|
+
rec.shape = loc # the factory for the :shape column is GEOS, so the
|
74
|
+
# value will be cast from geographic to GEOS.
|
75
|
+
RGeo::Geos.is_geos?(rec.shape) # => true
|
76
|
+
|
77
|
+
=== Installation
|
78
|
+
|
79
|
+
This adapter has the following requirements:
|
80
|
+
|
81
|
+
* Ruby 1.8.7 or later. Ruby 1.9.2 or later preferred.
|
82
|
+
* MySQL server 5.0 or later required for spatial extensions.
|
83
|
+
* \ActiveRecord 3.0.3 or later. Earlier versions will not work.
|
84
|
+
* rgeo gem 0.2.0 or later.
|
85
|
+
* rgeo-activerecord gem 0.2.0 or later.
|
86
|
+
* mysql gem 2.8 or later.
|
87
|
+
|
88
|
+
Install this adapter as a gem:
|
89
|
+
|
90
|
+
gem install activerecord-mysqlspatial-adapter
|
91
|
+
|
92
|
+
See the README for the "rgeo" gem, a required dependency, for further
|
93
|
+
installation information.
|
94
|
+
|
95
|
+
=== Development and support
|
96
|
+
|
97
|
+
Documentation is available at http://virtuoso.rubyforge.org/activerecord-mysqlspatial-adapter/README_rdoc.html
|
98
|
+
|
99
|
+
Source code is hosted on Github at http://github.com/dazuma/activerecord-mysqlspatial-adapter
|
100
|
+
|
101
|
+
Contributions are welcome. Fork the project on Github.
|
102
|
+
|
103
|
+
Report bugs on Github issues at http://github.org/dazuma/activerecord-mysqlspatial-adapter/issues
|
104
|
+
|
105
|
+
Contact the author at dazuma at gmail dot com.
|
106
|
+
|
107
|
+
=== Acknowledgments
|
108
|
+
|
109
|
+
RGeo is written by Daniel Azuma (http://www.daniel-azuma.com).
|
110
|
+
|
111
|
+
Development of RGeo is sponsored by GeoPage, Inc. (http://www.geopage.com).
|
112
|
+
|
113
|
+
This adapter implementation owes some debt to the spatial_adapter plugin
|
114
|
+
(http://github.com/fragility/spatial_adapter). Although we made a few
|
115
|
+
different design decisions for this adapter, studying the spatial_adapter
|
116
|
+
source gave us a head start on the implementation.
|
117
|
+
|
118
|
+
=== License
|
119
|
+
|
120
|
+
Copyright 2010 Daniel Azuma
|
121
|
+
|
122
|
+
All rights reserved.
|
123
|
+
|
124
|
+
Redistribution and use in source and binary forms, with or without
|
125
|
+
modification, are permitted provided that the following conditions are met:
|
126
|
+
|
127
|
+
* Redistributions of source code must retain the above copyright notice,
|
128
|
+
this list of conditions and the following disclaimer.
|
129
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
130
|
+
this list of conditions and the following disclaimer in the documentation
|
131
|
+
and/or other materials provided with the distribution.
|
132
|
+
* Neither the name of the copyright holder, nor the names of any other
|
133
|
+
contributors to this software, may be used to endorse or promote products
|
134
|
+
derived from this software without specific prior written permission.
|
135
|
+
|
136
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
137
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
138
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
139
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
140
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
141
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
142
|
+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
143
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
144
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
145
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
146
|
+
POSSIBILITY OF SUCH DAMAGE.
|
data/Version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
@@ -0,0 +1,234 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# MysqlSpatial adapter for ActiveRecord
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 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 'rgeo/active_record'
|
38
|
+
require 'active_record/connection_adapters/mysql_adapter'
|
39
|
+
|
40
|
+
|
41
|
+
# :stopdoc:
|
42
|
+
|
43
|
+
module Arel
|
44
|
+
module Visitors
|
45
|
+
VISITORS['mysqlspatial'] = ::Arel::Visitors::MySQL
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# :startdoc:
|
50
|
+
|
51
|
+
|
52
|
+
# The activerecord-mysqlspatial-adapter gem installs the *mysqlspatial*
|
53
|
+
# connection adapter into ActiveRecord.
|
54
|
+
|
55
|
+
module ActiveRecord
|
56
|
+
|
57
|
+
|
58
|
+
# ActiveRecord looks for the mysqlspatial_connection factory method in
|
59
|
+
# this class.
|
60
|
+
|
61
|
+
class Base
|
62
|
+
|
63
|
+
|
64
|
+
# Create a mysqlspatial connection adapter.
|
65
|
+
|
66
|
+
def self.mysqlspatial_connection(config_)
|
67
|
+
unless defined?(::Mysql)
|
68
|
+
begin
|
69
|
+
require 'mysql'
|
70
|
+
rescue ::LoadError
|
71
|
+
raise "!!! Missing the mysql gem. Add it to your Gemfile: gem 'mysql'"
|
72
|
+
end
|
73
|
+
unless defined?(::Mysql::Result) && ::Mysql::Result.method_defined?(:each_hash)
|
74
|
+
raise "!!! Outdated mysql gem. Upgrade to 2.8.1 or later. In your Gemfile: gem 'mysql', '2.8.1'. Or use gem 'mysql2'"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
config_ = config_.symbolize_keys
|
78
|
+
mysql_ = ::Mysql.init
|
79
|
+
mysql_.ssl_set(config_[:sslkey], config_[:sslcert], config_[:sslca], config_[:sslcapath], config_[:sslcipher]) if config_[:sslca] || config_[:sslkey]
|
80
|
+
default_flags_ = ::Mysql.const_defined?(:CLIENT_MULTI_RESULTS) ? ::Mysql::CLIENT_MULTI_RESULTS : 0
|
81
|
+
default_flags_ |= ::Mysql::CLIENT_FOUND_ROWS if ::Mysql.const_defined?(:CLIENT_FOUND_ROWS)
|
82
|
+
options_ = [config_[:host], config_[:username] ? config_[:username].to_s : 'root', config_[:password].to_s, config_[:database], config_[:port], config_[:socket], default_flags_]
|
83
|
+
ConnectionAdapters::MysqlSpatialAdapter.new(mysql_, logger, options_, config_)
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
module ConnectionAdapters # :nodoc:
|
91
|
+
|
92
|
+
class MysqlSpatialAdapter < MysqlAdapter # :nodoc:
|
93
|
+
|
94
|
+
|
95
|
+
ADAPTER_NAME = 'MysqlSpatial'.freeze
|
96
|
+
|
97
|
+
NATIVE_DATABASE_TYPES = MysqlAdapter::NATIVE_DATABASE_TYPES.merge(:geometry => {:name => "geometry"}, :point => {:name => "point"}, :line_string => {:name => "linestring"}, :polygon => {:name => "polygon"}, :geometry_collection => {:name => "geometrycollection"}, :multi_point => {:name => "multipoint"}, :multi_line_string => {:name => "multilinestring"}, :multi_polygon => {:name => "multipolygon"})
|
98
|
+
|
99
|
+
|
100
|
+
def native_database_types
|
101
|
+
NATIVE_DATABASE_TYPES
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def adapter_name
|
106
|
+
ADAPTER_NAME
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
def quote(value_, column_=nil)
|
111
|
+
if ::RGeo::Feature::Geometry.check_type(value_)
|
112
|
+
"GeomFromWKB(0x#{::RGeo::WKRep::WKBGenerator.new(:hex_format => true).generate(value_)},#{value_.srid})"
|
113
|
+
else
|
114
|
+
super
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
def add_index(table_name_, column_name_, options_={})
|
120
|
+
if options_[:spatial]
|
121
|
+
index_name_ = index_name(table_name_, :column => Array(column_name_))
|
122
|
+
if ::Hash === options_
|
123
|
+
index_name_ = options_[:name] || index_name_
|
124
|
+
end
|
125
|
+
execute "CREATE SPATIAL INDEX #{index_name_} ON #{table_name_} (#{Array(column_name_).join(", ")})"
|
126
|
+
else
|
127
|
+
super
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
def columns(table_name_, name_=nil)
|
133
|
+
result_ = execute("SHOW FIELDS FROM #{quote_table_name(table_name_)}", :skip_logging)
|
134
|
+
columns_ = []
|
135
|
+
result_.each do |field_|
|
136
|
+
columns_ << SpatialColumn.new(field_[0], field_[4], field_[1], field_[2] == "YES")
|
137
|
+
end
|
138
|
+
result_.free
|
139
|
+
columns_
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
def indexes(table_name_, name_=nil)
|
144
|
+
indexes_ = []
|
145
|
+
current_index_ = nil
|
146
|
+
result_ = execute("SHOW KEYS FROM #{quote_table_name(table_name_)}", name_)
|
147
|
+
result_.each do |row_|
|
148
|
+
if current_index_ != row_[2]
|
149
|
+
next if row_[2] == "PRIMARY" # skip the primary key
|
150
|
+
current_index_ = row_[2]
|
151
|
+
indexes_ << ::RGeo::ActiveRecord::SpatialIndexDefinition.new(row_[0], row_[2], row_[1] == "0", [], [], row_[10] == 'SPATIAL')
|
152
|
+
end
|
153
|
+
indexes_.last.columns << row_[4]
|
154
|
+
indexes_.last.lengths << row_[7]
|
155
|
+
end
|
156
|
+
result_.free
|
157
|
+
indexes_
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
class SpatialColumn < ConnectionAdapters::MysqlColumn # :nodoc:
|
162
|
+
|
163
|
+
|
164
|
+
def initialize(name_, default_, sql_type_=nil, null_=true)
|
165
|
+
super(name_, default_,sql_type_, null_)
|
166
|
+
@geometric_type = ::RGeo::ActiveRecord.geometric_type_from_name(sql_type_)
|
167
|
+
@ar_class = ::ActiveRecord::Base
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
def set_ar_class(val_)
|
172
|
+
@ar_class = val_
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
attr_reader :geometric_type
|
177
|
+
|
178
|
+
|
179
|
+
def spatial?
|
180
|
+
type == :geometry
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
def klass
|
185
|
+
type == :geometry ? ::RGeo::Feature::Geometry : super
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
def type_cast(value_)
|
190
|
+
type == :geometry ? SpatialColumn.convert_to_geometry(value_, @ar_class, name) : super
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
def type_cast_code(var_name_)
|
195
|
+
type == :geometry ? "::ActiveRecord::ConnectionAdapters::MysqlSpatialAdapter::SpatialColumn.convert_to_geometry(#{var_name_}, self.class, #{name.inspect})" : super
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
def simplified_type(sql_type_)
|
202
|
+
sql_type_ =~ /geometry|point|linestring|polygon/i ? :geometry : super
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
def self.convert_to_geometry(input_, ar_class_, column_)
|
207
|
+
case input_
|
208
|
+
when ::RGeo::Feature::Geometry
|
209
|
+
factory_ = ar_class_.rgeo_factory_for_column(column_, :srid => input_.srid)
|
210
|
+
::RGeo::Feature.cast(input_, factory_)
|
211
|
+
when ::String
|
212
|
+
marker_ = input_[4,1]
|
213
|
+
if marker_ == "\x00" || marker_ == "\x01"
|
214
|
+
factory_ = ar_class_.rgeo_factory_for_column(column_, :srid => input_[0,4].unpack(marker_ == "\x01" ? 'V' : 'N').first)
|
215
|
+
::RGeo::WKRep::WKBParser.new(factory_).parse(input_[4..-1])
|
216
|
+
else
|
217
|
+
factory_ = ar_class_.rgeo_factory_for_column(column_)
|
218
|
+
::RGeo::WKRep::WKTParser.new(factory_, :support_ewkt => true).parse(input_)
|
219
|
+
end
|
220
|
+
else
|
221
|
+
nil
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
end
|
data/test/tc_basic.rb
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Tests for the MysqlSpatial ActiveRecord adapter
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 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
|
+
require 'test/unit'
|
37
|
+
require 'rgeo/active_record/adapter_test_helper'
|
38
|
+
|
39
|
+
|
40
|
+
module RGeo
|
41
|
+
module ActiveRecord # :nodoc:
|
42
|
+
module MysqlSpatialAdapter # :nodoc:
|
43
|
+
module Tests # :nodoc:
|
44
|
+
|
45
|
+
class TestBasic < ::Test::Unit::TestCase # :nodoc:
|
46
|
+
|
47
|
+
DATABASE_CONFIG_PATH = ::File.dirname(__FILE__)+'/database.yml'
|
48
|
+
include AdapterTestHelper
|
49
|
+
|
50
|
+
define_test_methods do
|
51
|
+
|
52
|
+
|
53
|
+
def populate_ar_class(content_)
|
54
|
+
klass_ = create_ar_class
|
55
|
+
case content_
|
56
|
+
when :latlon_point
|
57
|
+
klass_.connection.create_table(:spatial_test) do |t_|
|
58
|
+
t_.column 'latlon', :point
|
59
|
+
end
|
60
|
+
end
|
61
|
+
klass_
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def test_create_simple_geometry
|
66
|
+
klass_ = create_ar_class
|
67
|
+
klass_.connection.create_table(:spatial_test) do |t_|
|
68
|
+
t_.column 'latlon', :geometry
|
69
|
+
end
|
70
|
+
assert_equal(::RGeo::Feature::Geometry, klass_.columns.last.geometric_type)
|
71
|
+
assert(klass_.cached_attributes.include?('latlon'))
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def test_create_point_geometry
|
76
|
+
klass_ = create_ar_class
|
77
|
+
klass_.connection.create_table(:spatial_test) do |t_|
|
78
|
+
t_.column 'latlon', :point
|
79
|
+
end
|
80
|
+
assert_equal(::RGeo::Feature::Point, klass_.columns.last.geometric_type)
|
81
|
+
assert(klass_.cached_attributes.include?('latlon'))
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def test_create_geometry_with_index
|
86
|
+
klass_ = create_ar_class
|
87
|
+
klass_.connection.create_table(:spatial_test, :options => 'ENGINE=MyISAM') do |t_|
|
88
|
+
t_.column 'latlon', :geometry, :null => false
|
89
|
+
end
|
90
|
+
klass_.connection.change_table(:spatial_test) do |t_|
|
91
|
+
t_.index([:latlon], :spatial => true)
|
92
|
+
end
|
93
|
+
assert(klass_.connection.indexes(:spatial_test).last.spatial)
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def test_set_and_get_point
|
98
|
+
klass_ = populate_ar_class(:latlon_point)
|
99
|
+
obj_ = klass_.new
|
100
|
+
assert_nil(obj_.latlon)
|
101
|
+
obj_.latlon = @factory.point(1, 2)
|
102
|
+
assert_equal(@factory.point(1, 2), obj_.latlon)
|
103
|
+
assert_equal(4326, obj_.latlon.srid)
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
def test_set_and_get_point_from_wkt
|
108
|
+
klass_ = populate_ar_class(:latlon_point)
|
109
|
+
obj_ = klass_.new
|
110
|
+
assert_nil(obj_.latlon)
|
111
|
+
obj_.latlon = 'SRID=1000;POINT(1 2)'
|
112
|
+
assert_equal(@factory.point(1, 2), obj_.latlon)
|
113
|
+
assert_equal(1000, obj_.latlon.srid)
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
def test_save_and_load_point
|
118
|
+
klass_ = populate_ar_class(:latlon_point)
|
119
|
+
obj_ = klass_.new
|
120
|
+
obj_.latlon = @factory.point(1, 2)
|
121
|
+
obj_.save!
|
122
|
+
id_ = obj_.id
|
123
|
+
obj2_ = klass_.find(id_)
|
124
|
+
assert_equal(@factory.point(1, 2), obj2_.latlon)
|
125
|
+
assert_equal(4326, obj2_.latlon.srid)
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
def test_save_and_load_point_from_wkt
|
130
|
+
klass_ = populate_ar_class(:latlon_point)
|
131
|
+
obj_ = klass_.new
|
132
|
+
obj_.latlon = 'SRID=1000;POINT(1 2)'
|
133
|
+
obj_.save!
|
134
|
+
id_ = obj_.id
|
135
|
+
obj2_ = klass_.find(id_)
|
136
|
+
assert_equal(@factory.point(1, 2), obj2_.latlon)
|
137
|
+
assert_equal(1000, obj2_.latlon.srid)
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
def test_readme_example
|
142
|
+
klass_ = create_ar_class
|
143
|
+
klass_.connection.create_table(:spatial_test, :options => 'ENGINE=MyISAM') do |t_|
|
144
|
+
t_.column(:latlon, :point, :null => false)
|
145
|
+
t_.line_string(:path)
|
146
|
+
t_.geometry(:shape)
|
147
|
+
end
|
148
|
+
klass_.connection.change_table(:spatial_test) do |t_|
|
149
|
+
t_.index(:latlon, :spatial => true)
|
150
|
+
end
|
151
|
+
klass_.class_eval do
|
152
|
+
self.rgeo_factory_generator = ::RGeo::Geos.method(:factory)
|
153
|
+
set_rgeo_factory_for_column(:latlon, ::RGeo::Geographic.spherical_factory)
|
154
|
+
end
|
155
|
+
rec_ = klass_.new
|
156
|
+
rec_.latlon = 'POINT(-122 47)'
|
157
|
+
loc_ = rec_.latlon
|
158
|
+
assert_equal(47, loc_.latitude)
|
159
|
+
rec_.shape = loc_
|
160
|
+
assert_equal(true, ::RGeo::Geos.is_geos?(rec_.shape))
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activerecord-mysqlspatial-adapter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Daniel Azuma
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-12-07 00:00:00 -08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rgeo-activerecord
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 2
|
31
|
+
- 0
|
32
|
+
version: 0.2.0
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: mysql
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 2
|
45
|
+
- 8
|
46
|
+
- 1
|
47
|
+
version: 2.8.1
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
description: This is an ActiveRecord connection adapter for MySQL Spatial Extensions. It is based on the stock MySQL adapter, but provides built-in support for spatial columns. It uses the RGeo library to represent spatial data in Ruby.
|
51
|
+
email: dazuma@gmail.com
|
52
|
+
executables: []
|
53
|
+
|
54
|
+
extensions: []
|
55
|
+
|
56
|
+
extra_rdoc_files:
|
57
|
+
- History.rdoc
|
58
|
+
- README.rdoc
|
59
|
+
files:
|
60
|
+
- lib/active_record/connection_adapters/mysqlspatial_adapter.rb
|
61
|
+
- History.rdoc
|
62
|
+
- README.rdoc
|
63
|
+
- test/tc_basic.rb
|
64
|
+
- Version
|
65
|
+
has_rdoc: true
|
66
|
+
homepage: http://virtuoso.rubyforge.org/activerecord-mysqlspatial-adapter
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 1
|
81
|
+
- 8
|
82
|
+
- 7
|
83
|
+
version: 1.8.7
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project: virtuoso
|
95
|
+
rubygems_version: 1.3.7
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: An ActiveRecord adapter for MySQL Spatial Extensions, based on RGeo.
|
99
|
+
test_files:
|
100
|
+
- test/tc_basic.rb
|