diff --git a/Rakefile b/Rakefile index d904afa..1598fb4 100644 --- a/Rakefile +++ b/Rakefile @@ -1,10 +1,11 @@ require 'rubygems' -require 'spec/rake/spectask' +require 'rspec/core/rake_task' [:mysql, :mysql2, :postgresql].each do |adapter| desc "Run specs for #{adapter} adapter" - Spec::Rake::SpecTask.new("spec:#{adapter.to_s}") do |t| - t.spec_files = FileList["spec/#{adapter}/*_spec.rb"] + RSpec::Core::RakeTask.new("spec:#{adapter.to_s}") do |spec| + spec.pattern = "spec/#{adapter}/*_spec.rb" + spec.rspec_opts = ['--backtrace'] end end diff --git a/lib/spatial_adapter/mysql.rb b/lib/spatial_adapter/mysql.rb index 8a3b6ed..6c13a8b 100644 --- a/lib/spatial_adapter/mysql.rb +++ b/lib/spatial_adapter/mysql.rb @@ -87,11 +87,9 @@ class SpatialMysqlColumn < MysqlColumn #MySql-specific geometry string parsing. By default, MySql returns geometries in strict wkb format with "0" characters in the first 4 positions. def self.string_to_geometry(string) return string unless string.is_a?(String) - begin - GeoRuby::SimpleFeatures::Geometry.from_ewkb(string[4..-1]) - rescue Exception => exception - nil - end + GeoRuby::SimpleFeatures::Geometry.from_ewkb(string[4..-1]) + rescue Exception + nil end end end diff --git a/lib/spatial_adapter/mysql2.rb b/lib/spatial_adapter/mysql2.rb index 1636483..0152860 100644 --- a/lib/spatial_adapter/mysql2.rb +++ b/lib/spatial_adapter/mysql2.rb @@ -86,11 +86,9 @@ class SpatialMysql2Column < Mysql2Column #MySql-specific geometry string parsing. By default, MySql returns geometries in strict wkb format with "0" characters in the first 4 positions. def self.string_to_geometry(string) return string unless string.is_a?(String) - begin - GeoRuby::SimpleFeatures::Geometry.from_ewkb(string[4..-1]) - rescue Exception => exception - nil - end + GeoRuby::SimpleFeatures::Geometry.from_ewkb(string[4..-1]) + rescue Exception + nil end end end diff --git a/lib/spatial_adapter/postgresql.rb b/lib/spatial_adapter/postgresql.rb index d0da480..117983c 100644 --- a/lib/spatial_adapter/postgresql.rb +++ b/lib/spatial_adapter/postgresql.rb @@ -5,11 +5,9 @@ include SpatialAdapter def postgis_version - begin - select_value("SELECT postgis_full_version()").scan(/POSTGIS="([\d\.]*)"/)[0][0] - rescue ActiveRecord::StatementInvalid - nil - end + select_value("SELECT postgis_full_version()").scan(/POSTGIS="([\d\.]*)"/)[0][0] + rescue ActiveRecord::StatementInvalid + nil end def postgis_major_version @@ -35,6 +33,15 @@ def native_database_types original_native_database_types.merge!(geometry_data_types) end + alias :original_type_cast :type_cast + def type_cast(value, column) + if value.kind_of?(GeoRuby::SimpleFeatures::Geometry) + value.as_hex_ewkb + else + original_type_cast(value, column) + end + end + alias :original_quote :quote #Redefines the quote method to add behaviour for when a Geometry is encountered def quote(value, column = nil) @@ -155,21 +162,18 @@ def indexes(table_name, name = nil) # Changed from upstread: link to pg_am to grab the index type (e.g. "gist") result = query(<<-SQL, name) SELECT distinct i.relname, d.indisunique, d.indkey, t.oid, am.amname - FROM pg_class t, pg_class i, pg_index d, pg_attribute a, pg_am am + FROM pg_class t + INNER JOIN pg_index d ON t.oid = d.indrelid + INNER JOIN pg_class i ON d.indexrelid = i.oid + INNER JOIN pg_attribute a ON a.attrelid = t.oid + INNER JOIN pg_am am ON i.relam = am.oid WHERE i.relkind = 'i' - AND d.indexrelid = i.oid AND d.indisprimary = 'f' - AND t.oid = d.indrelid AND t.relname = '#{table_name}' AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname IN (#{schemas}) ) - AND i.relam = am.oid - AND a.attrelid = t.oid ORDER BY i.relname SQL - - indexes = [] - indexes = result.map do |row| index_name = row[0] unique = row[1] == 't' @@ -180,29 +184,27 @@ def indexes(table_name, name = nil) # Changed from upstream: need to get the column types to test for spatial indexes columns = query(<<-SQL, "Columns for index #{row[0]} on #{table_name}").inject({}) {|attlist, r| attlist[r[1]] = [r[0], r[2]]; attlist} SELECT a.attname, a.attnum, t.typname - FROM pg_attribute a, pg_type t + FROM pg_attribute a + INNER JOIN pg_type t ON a.atttypid = t.oid WHERE a.attrelid = #{oid} AND a.attnum IN (#{indkey.join(",")}) - AND a.atttypid = t.oid SQL # Only GiST indexes on spatial columns denote a spatial index spatial = indtype == 'gist' && columns.size == 1 && (columns.values.first[1] == 'geometry' || columns.values.first[1] == 'geography') - column_names = indkey.map {|attnum| columns[attnum] ? columns[attnum][0] : nil } + column_names = indkey.map {|attnum| columns[attnum] ? columns[attnum][0] : nil }.compact ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, spatial) end - - indexes end def disable_referential_integrity(&block) #:nodoc: - if supports_disable_referential_integrity?() then + if supports_disable_referential_integrity? execute(tables_without_postgis.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";")) end yield ensure - if supports_disable_referential_integrity?() then + if supports_disable_referential_integrity? execute(tables_without_postgis.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";")) end end @@ -237,7 +239,6 @@ def column_spatial_info(table_name) end raw_geom_infos - end end @@ -272,8 +273,7 @@ def column(name, type, options = {}) end class PostgreSQLColumnDefinition < ColumnDefinition - attr_accessor :table_name - attr_accessor :srid, :with_z, :with_m, :geographic + attr_accessor :table_name, :srid, :with_z, :with_m, :geographic attr_reader :spatial def initialize(base = nil, name = nil, type=nil, limit=nil, default=nil, null=nil, srid=-1, with_z=false, with_m=false, geographic=false) @@ -304,13 +304,14 @@ def to_sql if spatial && !geographic type_sql = base.geometry_data_types[type.to_sym][:name] type_sql += "M" if with_m and !with_z - if with_m and with_z - dimension = 4 - elsif with_m or with_z - dimension = 3 - else - dimension = 2 - end + dimension = + if with_m and with_z + 4 + elsif with_m or with_z + 3 + else + 2 + end column_sql = "SELECT AddGeometryColumn('#{table_name}','#{name}',#{srid},'#{type_sql}',#{dimension})" column_sql += ";ALTER TABLE #{table_name} ALTER #{name} SET NOT NULL" if null == false diff --git a/lib/spatial_adapter/railtie.rb b/lib/spatial_adapter/railtie.rb index 7a2ab28..1668bb8 100644 --- a/lib/spatial_adapter/railtie.rb +++ b/lib/spatial_adapter/railtie.rb @@ -1,13 +1,14 @@ module SpatialAdapter class Railtie < Rails::Railtie initializer "spatial_adapter.load_current_database_adapter" do - adapter = ActiveRecord::Base.configurations[Rails.env]['adapter'] - begin - require "spatial_adapter/#{adapter}" - rescue LoadError - raise SpatialAdapter::NotCompatibleError.new("spatial_adapter does not currently support the #{adapter} database.") + ActiveSupport.on_load :active_record do + adapter = ActiveRecord::Base.configurations[Rails.env]['adapter'] + begin + require "spatial_adapter/#{adapter}" + rescue LoadError + raise SpatialAdapter::NotCompatibleError.new("spatial_adapter does not currently support the #{adapter} database.") + end end end end end - diff --git a/spec/postgresql/connection_adapter_spec.rb b/spec/postgresql/connection_adapter_spec.rb index 1c6727c..7e2afbb 100644 --- a/spec/postgresql/connection_adapter_spec.rb +++ b/spec/postgresql/connection_adapter_spec.rb @@ -8,7 +8,17 @@ postgis_connection @connection = ActiveRecord::Base.connection end - + + describe '#native_database_types' do + it 'should include the geometry types' do + @connection.native_database_types.should include(@connection.geometry_data_types) + end + + it 'should include the basic types' do + @connection.native_database_types.should include(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES) + end + end + describe '#postgis_version' do it 'should report a version number if PostGIS is installed' do @connection.should_receive(:select_value).with('SELECT postgis_full_version()').and_return('POSTGIS="1.5.0" GEOS="3.2.0-CAPI-1.6.0" PROJ="Rel. 4.7.1, 23 September 2009" LIBXML="2.7.6" USE_STATS') @@ -209,19 +219,18 @@ end describe "#add_index" do - after :each do - @connection.should_receive(:execute).with(any_args()) - @connection.remove_index('geometry_models', 'geom') - end - it "should create a spatial index given :spatial => true" do - @connection.should_receive(:execute).with(/using gist/i) @connection.add_index('geometry_models', 'geom', :spatial => true) + @connection.indexes('geometry_models').first.spatial.should be_true + @connection.indexes('geometry_models').first.columns.should == ['geom'] + @connection.remove_index('geometry_models', 'geom') end it "should not create a spatial index unless specified" do - @connection.should_not_receive(:execute).with(/using gist/i) @connection.add_index('geometry_models', 'extra') + @connection.indexes('geometry_models').first.spatial.should be_false + @connection.indexes('geometry_models').first.columns.should == ['extra'] + @connection.remove_index('geometry_models', 'extra') end end end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3c28c42..cf95f45 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,7 +1,7 @@ require 'rubygems' -require 'spec' +require 'rspec' require 'geo_ruby' -gem 'activerecord', '=3.0.3' +gem 'activerecord', '>=3.0.3' require 'active_record' $:.unshift((File.join(File.dirname(__FILE__), '..', 'lib')))