diff --git a/Appraisals b/Appraisals index 025ccfe..a69bd35 100644 --- a/Appraisals +++ b/Appraisals @@ -1,7 +1,5 @@ -appraise 'rgeo-0.4.0' do - gem 'rgeo', '0.4.0' -end - -appraise 'rgeo-0.6.0' do +appraise 'current' do + gem 'activerecord', '4.2.9' + gem 'mysql2', '0.3.21' gem 'rgeo', '0.6.0' end diff --git a/Gemfile b/Gemfile index de8781e..3052c04 100644 --- a/Gemfile +++ b/Gemfile @@ -35,7 +35,3 @@ source "https://rubygems.org" gemspec - -# This dependency is here because gemspecs can't use git sources. -# It overrides the less specific dependency in gemspec. -gem 'rgeo-activerecord', git: 'https://github.com/rgeo/rgeo-activerecord.git', branch: '1.0' diff --git a/activerecord-mysql2spatial-adapter.gemspec b/activerecord-mysql2spatial-adapter.gemspec index 7d20518..241fe58 100644 --- a/activerecord-mysql2spatial-adapter.gemspec +++ b/activerecord-mysql2spatial-adapter.gemspec @@ -47,8 +47,8 @@ ['Version'] s_.extra_rdoc_files = ::Dir.glob("*.rdoc") s_.platform = ::Gem::Platform::RUBY - s_.add_dependency('activerecord', '>= 4.0', '< 4.2') - s_.add_dependency('rgeo-activerecord', '~> 1.0') + s_.add_dependency('activerecord', '~> 4.2.9') + s_.add_dependency('rgeo-activerecord', '~> 2.1.1') s_.add_dependency('mysql2', '>= 0.2.13', '< 0.4.0') s_.add_development_dependency('appraisal') s_.add_development_dependency('pry') diff --git a/gemfiles/rgeo_0.6.0.gemfile b/gemfiles/current.gemfile similarity index 54% rename from gemfiles/rgeo_0.6.0.gemfile rename to gemfiles/current.gemfile index aed7619..e469285 100644 --- a/gemfiles/rgeo_0.6.0.gemfile +++ b/gemfiles/current.gemfile @@ -2,7 +2,8 @@ source "https://rubygems.org" -gem "rgeo-activerecord", git: "https://github.com/rgeo/rgeo-activerecord.git", branch: "1.0" +gem "activerecord", "4.2.9" +gem "mysql2", "0.3.21" gem "rgeo", "0.6.0" gemspec path: "../" diff --git a/gemfiles/rgeo_0.4.0.gemfile b/gemfiles/rgeo_0.4.0.gemfile deleted file mode 100644 index a8d35c2..0000000 --- a/gemfiles/rgeo_0.4.0.gemfile +++ /dev/null @@ -1,8 +0,0 @@ -# This file was generated by Appraisal - -source "https://rubygems.org" - -gem "rgeo-activerecord", git: "https://github.com/rgeo/rgeo-activerecord.git", branch: "1.0" -gem "rgeo", "0.4.0" - -gemspec path: "../" diff --git a/lib/active_record/connection_adapters/mysql2spatial_adapter.rb b/lib/active_record/connection_adapters/mysql2spatial_adapter.rb index e3ec791..87bae04 100644 --- a/lib/active_record/connection_adapters/mysql2spatial_adapter.rb +++ b/lib/active_record/connection_adapters/mysql2spatial_adapter.rb @@ -31,8 +31,6 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # ----------------------------------------------------------------------------- -; - require 'rgeo/active_record' require 'active_record/connection_adapters/mysql2_adapter' @@ -88,3 +86,4 @@ module Mysql2SpatialAdapter require 'active_record/connection_adapters/mysql2spatial_adapter/main_adapter.rb' require 'active_record/connection_adapters/mysql2spatial_adapter/spatial_column.rb' require 'active_record/connection_adapters/mysql2spatial_adapter/arel_tosql.rb' +require 'active_record/type/spatial.rb' diff --git a/lib/active_record/connection_adapters/mysql2spatial_adapter/main_adapter.rb b/lib/active_record/connection_adapters/mysql2spatial_adapter/main_adapter.rb index 9d75a0b..da50ef3 100644 --- a/lib/active_record/connection_adapters/mysql2spatial_adapter/main_adapter.rb +++ b/lib/active_record/connection_adapters/mysql2spatial_adapter/main_adapter.rb @@ -31,8 +31,6 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # ----------------------------------------------------------------------------- -; - # :stopdoc: @@ -111,11 +109,11 @@ def add_index(table_name_, column_name_, options_={}) def columns(table_name_, name_=nil) - result_ = execute("SHOW FIELDS FROM #{quote_table_name(table_name_)}", :skip_logging) + result_ = @connection.query "SHOW FULL FIELDS FROM #{quote_table_name(table_name_)}" columns_ = [] result_.each(:symbolize_keys => true, :as => :hash) do |field_| columns_ << SpatialColumn.new(@rgeo_factory_settings, table_name_.to_s, - field_[:Field], field_[:Default], field_[:Type], field_[:Null] == "YES") + field_[:Field], field_[:Default], lookup_cast_type(field_[:Type]), field_[:Type], field_[:Null] == "YES", field_[:Collation], field_[:Extra]) end columns_ end @@ -147,6 +145,15 @@ def indexes(table_name_, name_=nil) indexes_ end + protected + + def initialize_type_map(m) + super + register_class_with_limit m, %r(geometry)i, Type::Spatial + m.alias_type %r(point)i, 'geometry' + m.alias_type %r(linestring)i, 'geometry' + m.alias_type %r(polygon)i, 'geometry' + end end diff --git a/lib/active_record/connection_adapters/mysql2spatial_adapter/spatial_column.rb b/lib/active_record/connection_adapters/mysql2spatial_adapter/spatial_column.rb index 7b10e61..e01ebf0 100644 --- a/lib/active_record/connection_adapters/mysql2spatial_adapter/spatial_column.rb +++ b/lib/active_record/connection_adapters/mysql2spatial_adapter/spatial_column.rb @@ -31,116 +31,26 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # ----------------------------------------------------------------------------- -; - # :stopdoc: module ActiveRecord - module ConnectionAdapters - module Mysql2SpatialAdapter - - - # ActiveRecord 3.2 uses ConnectionAdapters::Mysql2Adapter::Column - # whereas 3.0 and 3.1 use ConnectionAdapters::Mysql2Column - column_base_class_ = defined?(ConnectionAdapters::Mysql2Adapter::Column) ? - ConnectionAdapters::Mysql2Adapter::Column : ConnectionAdapters::Mysql2Column - - class SpatialColumn < column_base_class_ - - + class SpatialColumn < ConnectionAdapters::Mysql2Adapter::Column FACTORY_SETTINGS_CACHE = {} - - def initialize(factory_settings_, table_name_, name_, default_, sql_type_=nil, null_=true) - @factory_settings = factory_settings_ - @table_name = table_name_ - super(name_, default_,sql_type_, null_) - @geometric_type = ::RGeo::ActiveRecord.geometric_type_from_name(sql_type_) + def initialize(factory_settings_, table_name_, name_, default_, cast_type_ = nil, sql_type_ = nil, null_ = true, collation_ = nil, extra_ = "") + super(name_, default_, cast_type_, sql_type_, null_, collation_, false, extra_) if type == :spatial - @limit = { type: @geometric_type.type_name.underscore } + cast_type.set_geo_params(factory_settings_, table_name_, ::RGeo::ActiveRecord.geometric_type_from_name(sql_type_)) end FACTORY_SETTINGS_CACHE[factory_settings_.object_id] = factory_settings_ end - - attr_reader :geometric_type - - - def spatial? - type == :spatial - end - - - def klass - type == :spatial ? ::RGeo::Feature::Geometry : super - end - - - def type_cast(value_) - if type == :spatial - SpatialColumn.convert_to_geometry(value_, @factory_settings, @table_name, name) - else - super - end - end - - - def type_cast_code(var_name_) - if type == :spatial - "::ActiveRecord::ConnectionAdapters::Mysql2SpatialAdapter::SpatialColumn.convert_to_geometry("+ - "#{var_name_}, ::ActiveRecord::ConnectionAdapters::Mysql2SpatialAdapter::SpatialColumn::"+ - "FACTORY_SETTINGS_CACHE[#{@factory_settings.object_id}], #{@table_name.inspect}, #{name.inspect})" - else - super - end - end - - - private - - def simplified_type(sql_type_) - sql_type_ =~ /geometry|point|linestring|polygon/i ? :spatial : super - end - - - def self.convert_to_geometry(input_, factory_settings_, table_name_, column_) - case input_ - when ::RGeo::Feature::Geometry - factory_ = factory_settings_.get_column_factory(table_name_, column_, :srid => input_.srid) - ::RGeo::Feature.cast(input_, factory_) rescue nil - when ::String - marker_ = input_[4,1] - if marker_ == "\x00" || marker_ == "\x01" - factory_ = factory_settings_.get_column_factory(table_name_, column_, - :srid => input_[0,4].unpack(marker_ == "\x01" ? 'V' : 'N').first) - ::RGeo::WKRep::WKBParser.new(factory_).parse(input_[4..-1]) rescue nil - elsif input_[0,10] =~ /[0-9a-fA-F]{8}0[01]/ - srid_ = input_[0,8].to_i(16) - if input[9,1] == '1' - srid_ = [srid_].pack('V').unpack('N').first - end - factory_ = factory_settings_.get_column_factory(table_name_, column_, :srid => srid_) - ::RGeo::WKRep::WKBParser.new(factory_).parse(input_[8..-1]) rescue nil - else - factory_ = factory_settings_.get_column_factory(table_name_, column_) - ::RGeo::WKRep::WKTParser.new(factory_, :support_ewkt => true).parse(input_) rescue nil - end - else - nil - end - end - - end - - end - end - end # :startdoc: diff --git a/lib/active_record/type/spatial.rb b/lib/active_record/type/spatial.rb new file mode 100644 index 0000000..f34df6d --- /dev/null +++ b/lib/active_record/type/spatial.rb @@ -0,0 +1,53 @@ +module ActiveRecord + module Type + class Spatial < Value # :nodoc: + def type + :spatial + end + + def spatial? + type == :spatial + end + + def klass + type == :spatial ? ::RGeo::Feature::Geometry : super + end + + def set_geo_params(factory_settings, table_name, geometric_type) + @factory_settings = factory_settings + @table_name = table_name + @geometric_type = geometric_type + end + + private + + def cast_value(value) + case value + when ::RGeo::Feature::Geometry + factory = @factory_settings.get_column_factory(@table_name, @column, :srid => value.srid) + ::RGeo::Feature.cast(value, factory) rescue nil + when ::String + marker = value[4,1] + if marker == "\x00" || marker == "\x01" + factory = @factory_settings.get_column_factory(@table_name, @column, + :srid => value[0,4].unpack(marker == "\x01" ? 'V' : 'N').first) + ::RGeo::WKRep::WKBParser.new(factory).parse(value[4..-1]) rescue nil + elsif value[0,10] =~ /[0-9a-fA-F]{8}0[01]/ + srid = value[0,8].to_i(16) + if value[9,1] == '1' + srid = [srid].pack('V').unpack('N').first + end + factory = @factory_settings.get_column_factory(@table_name, @column, :srid => srid) + ::RGeo::WKRep::WKBParser.new(factory).parse(value[8..-1]) rescue nil + else + factory = @factory_settings.get_column_factory(@table_name, @column) + ::RGeo::WKRep::WKTParser.new(factory, support_ewkt: true).parse(value) rescue nil + end + else + nil + end + end + + end + end +end