Skip to content

Commit

Permalink
Merge pull request #4 from stadia/devel
Browse files Browse the repository at this point in the history
change the type of SpatialColumn
  • Loading branch information
stadia authored Feb 9, 2017
2 parents 3b29a85 + 2c0758a commit 9a32baf
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 34 deletions.
3 changes: 3 additions & 0 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ Bundler/OrderedGems:
# Offense count: 3
Lint/HandleExceptions:
Exclude:
- 'test/tasks_test.rb'
- 'test/test_helper.rb'
- 'test/spatial_types_test.rb'

# Offense count: 1
# Cop supports --auto-correct.
Expand Down Expand Up @@ -166,6 +168,7 @@ Style/ParallelAssignment:
Style/PredicateName:
Exclude:
- 'lib/active_record/connection_adapters/mysql2rgeo/spatial_table_definition.rb'
- 'lib/active_record/connection_adapters/mysql2rgeo/spatial_column.rb'

# Offense count: 5
# Cop supports --auto-correct.
Expand Down
3 changes: 2 additions & 1 deletion .travis.install-mysql-5.7.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ echo mysql-apt-config mysql-apt-config/select-server select mysql-5.7 | sudo deb
wget https://dev.mysql.com/get/mysql-apt-config_0.8.1-1_all.deb
sudo dpkg --install mysql-apt-config_0.8.1-1_all.deb
sudo apt-get update -q && sudo apt-get install -q -y -o Dpkg::Options::=--force-confnew mysql-server
sudo mysql_upgrade
sudo mysql_upgrade -uroot
sudo service mysql restart
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ addons:
before_install:
- bash .travis.install-mysql-5.7.sh
- mysql -u root -e 'CREATE DATABASE IF NOT EXISTS mysql2rgeo_adapter_test;'
- mysql -u root -e 'CREATE DATABASE IF NOT EXISTS mysql2rgeo_tasks_test;'
- mkdir tmp && touch tmp/tmp.sql
script: bundle exec rake test
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def visit_Arel_Nodes_SelectCore(o, collector)
def visit_Arel_Attributes_Attribute(o, collector)
join_name = o.relation.table_alias || o.relation.name

collector << if (!column_for(o).nil? && column_for(o).type == :spatial) && !collector.value.include?(" WHERE ")
collector << if (!column_for(o).nil? && column_for(o).type == :geometry) && !collector.value.include?(" WHERE ")
"ST_AsText(#{quote_table_name join_name}.#{quote_column_name o.name}) as #{quote_column_name o.name}"
else
"#{quote_table_name join_name}.#{quote_column_name o.name}"
Expand Down
24 changes: 12 additions & 12 deletions lib/active_record/connection_adapters/mysql2rgeo/column_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,46 @@ module ConnectionAdapters
module Mysql2Rgeo
module ColumnMethods
def spatial(name, options = {})
raise "You must set a type. For example: 't.spatial limit: { type: 'point' }'" if options[:limit].blank? || options[:limit][:type].blank?
raise "You must set a type. For example: 't.spatial :object1, limit: { type: 'point' }'" if options[:limit].blank? || options[:limit][:type].blank?
column(name, options[:limit][:type], options)
end

def geography(*args, **options)
args.each { |name| column(name, :geometry, options) }
end

def geometry(*args, multi: false, **options)
multi ? multi_geometry(*args, **options) : args.each { |name| column(name, :geometry, options) }
end

def multi_geometry(*args, **options)
def geometrycollection(*args, **options)
args.each { |name| column(name, :geometrycollection, options) }
end

def point(*args, multi: false, **options)
multi ? multi_point(*args, **options) : args.each { |name| column(name, :point, options) }
end

def multi_point(*args, **options)
def multipoint(*args, **options)
args.each { |name| column(name, :multipoint, options) }
end

def linestring(*args, multi: false, **options)
multi ? multi_linestring(*args, **options) : args.each { |name| column(name, :linestring, options) }
end

def multi_linestring(*args, **options)
def multilinestring(*args, **options)
args.each { |name| column(name, :multilinestring, options) }
end

def polygon(*args, multi: false, **options)
type = multi ? :multipolygon : :polygon
args.each { |name| column(name, type, options) }
multi ? multipolygon(*args, **options) : args.each { |name| column(name, :polygon, options) }
end

def multi_polygon(*args, **options)
polygon(args, true, options)
def multipolygon(*args, **options)
args.each { |name| column(name, :multipolygon, options) }
end

alias multi_point multipoint
alias multi_geometry geometrycollection
alias multi_linestring multilinestring
alias multi_polygon multipolygon
end

MySQL::Table.send(:include, ColumnMethods)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,6 @@ def create_table_definition(*args)
Mysql2Rgeo::TableDefinition.new(*args)
end

def type_cast(value, column = nil)
super
rescue TypeError
value.to_s
end

def initialize_type_map(m)
super
%w(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ def srid=(value)
@srid = value
end
end

SpatialIndexDefinition = Struct.new(*IndexDefinition.members, :spatial)
end
end
end
12 changes: 7 additions & 5 deletions lib/active_record/connection_adapters/mysql2rgeo_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,13 @@ def indexes(table_name, _name = nil) #:nodoc:
mysql_index_type = row[:Index_type].downcase.to_sym
index_type = INDEX_TYPES.include?(mysql_index_type) ? mysql_index_type : nil
index_using = INDEX_USINGS.include?(mysql_index_type) ? mysql_index_type : nil
if mysql_index_type != :spatial
indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], [], nil, nil, index_type, index_using, row[:Index_comment].presence)
else
indexes << RGeo::ActiveRecord::SpatialIndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique] == 0, [], [], row[:Index_type] == "SPATIAL")
end
options = [row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], [], nil, nil, index_type, index_using, row[:Index_comment].presence]
indexes << if mysql_index_type == :spatial
options.push(true)
Mysql2Rgeo::SpatialIndexDefinition.new(*options)
else
IndexDefinition.new(*options)
end
end

indexes.last.columns << row[:Column_name]
Expand Down
10 changes: 3 additions & 7 deletions lib/active_record/type/spatial.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,15 @@ def self.parse_sql_type(sql_type)
end

def klass
type == :spatial ? RGeo::Feature::Geometry : super
type == :geometry ? RGeo::Feature::Geometry : super
end

def type
:spatial
end

def self.type
:spatial
:geometry
end

def spatial?
type == :spatial
true
end

def spatial_factory
Expand Down
4 changes: 2 additions & 2 deletions test/ddl_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,12 @@ def test_column_types
klass.reset_column_information
assert_equal :integer, klass.columns[-3].type
assert_equal :string, klass.columns[-2].type
assert_equal :spatial, klass.columns[-1].type
assert_equal :geometry, klass.columns[-1].type
end

def test_reload_dumped_schema
klass.connection.create_table(:spatial_models, force: true) do |t|
t.geography "latlon1", limit: { srid: 4326, type: "point", geographic: true }
t.geometry "latlon1", limit: { srid: 4326, type: "point", geographic: true }
end
klass.reset_column_information
col = klass.columns.last
Expand Down
89 changes: 89 additions & 0 deletions test/spatial_types_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
require "test_helper"
require "active_record/schema_dumper"

class Mysql2SpatialTypesTest < ActiveSupport::TestCase # :nodoc:
NEW_CONNECTION = {
"adapter" => "mysql2rgeo",
"host" => "127.0.0.1",
"database" => "mysql2rgeo_tasks_test",
"username" => "root"
}.freeze

def setup
setup_database_tasks
connection.create_table("spatial_types", force: true) do |t|
t.geometry :geometry_field
t.polygon :polygon_field, null: false, index: { type: :spatial }
t.point :point_field
t.linestring :linestring_field

t.geometry :geometry_multi, multi: true
t.polygon :polygon_multi, multi: true
t.point :point_multi, multi: true
t.linestring :linestring_multi, multi: true
end
end

def teardown
connection.drop_table "spatial_types", if_exists: true
end

def test_schema_dump_includes_spatial_types
File.open(tmp_sql_filename, "w:utf-8") do |file|
ActiveRecord::SchemaDumper.dump(connection, file)
end
# schema = File.read(tmp_sql_filename)

# assert_match %r{t.geometry\s+"geometry_field"$}, schema
# assert_match %r{t.polygon\s+"polygon_field",\s+null: false$}, schema
# assert_match %r{t.point\s+"point_field"$}, schema
# assert_match %r{t.linestring\s+"linestring_field"$}, schema
#
# assert_match %r{t.geometry\s+"geometry_multi",\s+multi: true$}, schema
# assert_match %r{t.polygon\s+"polygon_multi",\s+multi: true$}, schema
# assert_match %r{t.point\s+"point_multi",\s+multi: true$}, schema
# assert_match %r{t.linestring\s+"linestring_multi",\s+multi: true$}, schema
end

def test_schema_dump_can_be_restored
File.open(tmp_sql_filename, "w:utf-8") do |file|
ActiveRecord::SchemaDumper.dump(connection, file)
end
schema = File.read(tmp_sql_filename)
connection.drop_table "spatial_types", if_exists: true

eval schema

File.open(tmp_sql_filename, "w:utf-8") do |file|
ActiveRecord::SchemaDumper.dump(connection, file)
end
schema2 = File.read(tmp_sql_filename)

assert_equal schema, schema2
end

private

def connection
ActiveRecord::Base.connection
end

def tmp_sql_filename
File.expand_path("../tmp/tmp.sql", ::File.dirname(__FILE__))
end

def setup_database_tasks
FileUtils.rm_f(tmp_sql_filename)
FileUtils.mkdir_p(::File.dirname(tmp_sql_filename))
drop_db_if_exists
ActiveRecord::Tasks::MySQLDatabaseTasks.new(NEW_CONNECTION).create
rescue ActiveRecord::Tasks::DatabaseAlreadyExists
# ignore
end

def drop_db_if_exists
ActiveRecord::Tasks::MySQLDatabaseTasks.new(NEW_CONNECTION).drop
rescue ActiveRecord::Tasks::DatabaseAlreadyExists
# ignore
end
end
Loading

0 comments on commit 9a32baf

Please sign in to comment.