ar-postgis 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +7 -0
  2. data/Documentation.rdoc +292 -0
  3. data/History.rdoc +147 -0
  4. data/LICENSE.txt +29 -0
  5. data/README.rdoc +78 -0
  6. data/lib/active_record/connection_adapters/postgis_adapter.rb +38 -0
  7. data/lib/active_record/connection_adapters/postgis_adapter/rails4/create_connection.rb +29 -0
  8. data/lib/active_record/connection_adapters/postgis_adapter/rails4/databases.rake +17 -0
  9. data/lib/active_record/connection_adapters/postgis_adapter/rails4/main_adapter.rb +202 -0
  10. data/lib/active_record/connection_adapters/postgis_adapter/rails4/postgis_database_tasks.rb +204 -0
  11. data/lib/active_record/connection_adapters/postgis_adapter/rails4/spatial_column.rb +184 -0
  12. data/lib/active_record/connection_adapters/postgis_adapter/rails4/spatial_table_definition.rb +121 -0
  13. data/lib/active_record/connection_adapters/postgis_adapter/railtie.rb +3 -0
  14. data/lib/active_record/connection_adapters/postgis_adapter/shared/arel_tosql.rb +23 -0
  15. data/lib/active_record/connection_adapters/postgis_adapter/shared/common_adapter_methods.rb +46 -0
  16. data/lib/active_record/connection_adapters/postgis_adapter/shared/railtie.rb +13 -0
  17. data/lib/active_record/connection_adapters/postgis_adapter/shared/setup.rb +21 -0
  18. data/lib/active_record/connection_adapters/postgis_adapter/version.rb +7 -0
  19. data/lib/activerecord-postgis-adapter.rb +1 -0
  20. data/test/database.yml +5 -0
  21. data/test/tc_basic.rb +212 -0
  22. data/test/tc_ddl.rb +303 -0
  23. data/test/tc_nested_class.rb +48 -0
  24. data/test/tc_spatial_queries.rb +126 -0
  25. data/test/tc_tasks.rb +112 -0
  26. metadata +149 -0
@@ -0,0 +1,184 @@
1
+ module ActiveRecord # :nodoc:
2
+
3
+ module ConnectionAdapters # :nodoc:
4
+
5
+ module PostGISAdapter # :nodoc:
6
+
7
+
8
+ class SpatialColumn < ConnectionAdapters::PostgreSQLColumn # :nodoc:
9
+
10
+
11
+ def initialize(factory_settings_, table_name_, name_, default_, oid_type_, sql_type_=nil, null_=true, opts_=nil)
12
+ @factory_settings = factory_settings_
13
+ @table_name = table_name_
14
+ @geographic = sql_type_ =~ /geography/i ? true : false
15
+ if opts_
16
+ # This case comes from an entry in the geometry_columns table
17
+ @geometric_type = ::RGeo::ActiveRecord.geometric_type_from_name(opts_[:type]) ||
18
+ ::RGeo::Feature::Geometry
19
+ @srid = opts_[:srid].to_i
20
+ @has_z = opts_[:has_z] ? true : false
21
+ @has_m = opts_[:has_m] ? true : false
22
+ elsif @geographic
23
+ # Geographic type information is embedded in the SQL type
24
+ @geometric_type = ::RGeo::Feature::Geometry
25
+ @srid = 4326
26
+ @has_z = @has_m = false
27
+ if sql_type_ =~ /geography\((.*)\)$/i
28
+ params_ = $1.split(',')
29
+ if params_.size >= 2
30
+ if params_.first =~ /([a-z]+[^zm])(z?)(m?)/i
31
+ @has_z = $2.length > 0
32
+ @has_m = $3.length > 0
33
+ @geometric_type = ::RGeo::ActiveRecord.geometric_type_from_name($1)
34
+ end
35
+ if params_.last =~ /(\d+)/
36
+ @srid = $1.to_i
37
+ end
38
+ end
39
+ end
40
+ elsif sql_type_ =~ /geography|geometry|point|linestring|polygon/i
41
+ # Just in case there is a geometry column with no geometry_columns entry.
42
+ @geometric_type = ::RGeo::Feature::Geometry
43
+ @srid = @has_z = @has_m = nil
44
+ else
45
+ # Non-spatial column
46
+ @geometric_type = @has_z = @has_m = @srid = nil
47
+ end
48
+ super(name_, default_, oid_type_, sql_type_, null_)
49
+ if spatial?
50
+ if @srid
51
+ @limit = {:srid => @srid, :type => @geometric_type.type_name.underscore}
52
+ @limit[:has_z] = true if @has_z
53
+ @limit[:has_m] = true if @has_m
54
+ @limit[:geographic] = true if @geographic
55
+ else
56
+ @limit = {:no_constraints => true}
57
+ end
58
+ end
59
+ end
60
+
61
+
62
+ attr_reader :geographic
63
+ attr_reader :srid
64
+ attr_reader :geometric_type
65
+ attr_reader :has_z
66
+ attr_reader :has_m
67
+
68
+ alias_method :geographic?, :geographic
69
+ alias_method :has_z?, :has_z
70
+ alias_method :has_m?, :has_m
71
+
72
+
73
+ def spatial?
74
+ type == :spatial || type == :geography
75
+ end
76
+
77
+
78
+ def has_spatial_constraints?
79
+ !@srid.nil?
80
+ end
81
+
82
+
83
+ def klass
84
+ spatial? ? ::RGeo::Feature::Geometry : super
85
+ end
86
+
87
+
88
+ def type_cast(value_)
89
+ if spatial?
90
+ SpatialColumn.convert_to_geometry(value_, @factory_settings, @table_name, name,
91
+ @geographic, @srid, @has_z, @has_m)
92
+ else
93
+ super
94
+ end
95
+ end
96
+
97
+
98
+ private
99
+
100
+
101
+ def simplified_type(sql_type_)
102
+ sql_type_ =~ /geography|geometry|point|linestring|polygon/i ? :spatial : super
103
+ end
104
+
105
+
106
+ def self.convert_to_geometry(input_, factory_settings_, table_name_, column_, geographic_, srid_, has_z_, has_m_)
107
+ if srid_
108
+ constraints_ = {:geographic => geographic_, :has_z_coordinate => has_z_,
109
+ :has_m_coordinate => has_m_, :srid => srid_}
110
+ else
111
+ constraints_ = nil
112
+ end
113
+ if ::RGeo::Feature::Geometry === input_
114
+ factory_ = factory_settings_.get_column_factory(table_name_, column_, constraints_)
115
+ ::RGeo::Feature.cast(input_, factory_) rescue nil
116
+ elsif input_.respond_to?(:to_str)
117
+ input_ = input_.to_str
118
+ if input_.length == 0
119
+ nil
120
+ else
121
+ factory_ = factory_settings_.get_column_factory(table_name_, column_, constraints_)
122
+ marker_ = input_[0,1]
123
+ if marker_ == "\x00" || marker_ == "\x01" || input_[0,4] =~ /[0-9a-fA-F]{4}/
124
+ ::RGeo::WKRep::WKBParser.new(factory_, :support_ewkb => true).parse(input_) rescue nil
125
+ else
126
+ ::RGeo::WKRep::WKTParser.new(factory_, :support_ewkt => true).parse(input_) rescue nil
127
+ end
128
+ end
129
+ else
130
+ nil
131
+ end
132
+ end
133
+
134
+
135
+ end
136
+
137
+
138
+ # Register spatial types with the postgres OID mechanism
139
+ # so we can recognize custom columns coming from the database.
140
+
141
+ class SpatialOID < PostgreSQLAdapter::OID::Type # :nodoc:
142
+
143
+ def initialize(factory_generator_)
144
+ @factory_generator = factory_generator_
145
+ end
146
+
147
+ def type_cast(value_)
148
+ return if value_.nil?
149
+ ::RGeo::WKRep::WKBParser.new(@factory_generator, :support_ewkb => true).parse(value_) rescue nil
150
+ end
151
+
152
+ end
153
+
154
+ PostgreSQLAdapter::OID.register_type('geometry', SpatialOID.new(nil))
155
+ PostgreSQLAdapter::OID.register_type('geography', SpatialOID.new(::RGeo::Geographic.method(:spherical_factory)))
156
+
157
+
158
+ # This is a hack to ActiveRecord::ModelSchema. We have to "decorate" the decorate_columns
159
+ # method to apply class-specific customizations to spatial type casting.
160
+
161
+ module DecorateColumnsModification # :nodoc:
162
+
163
+ def decorate_columns(columns_hash_)
164
+ columns_hash_ = super(columns_hash_)
165
+ return unless columns_hash_
166
+ canonical_columns_ = self.columns_hash
167
+ columns_hash_.each do |name_, col_|
168
+ if col_.is_a?(SpatialOID) && (canonical_ = canonical_columns_[name_]) && canonical_.spatial?
169
+ columns_hash_[name_] = canonical_
170
+ end
171
+ end
172
+ columns_hash_
173
+ end
174
+
175
+ end
176
+
177
+ ::ActiveRecord::Base.extend(DecorateColumnsModification)
178
+
179
+
180
+ end
181
+
182
+ end
183
+
184
+ end
@@ -0,0 +1,121 @@
1
+ module ActiveRecord # :nodoc:
2
+
3
+ module ConnectionAdapters # :nodoc:
4
+
5
+ module PostGISAdapter # :nodoc:
6
+
7
+
8
+ class TableDefinition < ConnectionAdapters::PostgreSQLAdapter::TableDefinition # :nodoc:
9
+
10
+ def initialize(types_, name_, temporary_, options_, as_, base_)
11
+ @base = base_
12
+ @spatial_columns_hash = {}
13
+ super(types_, name_, temporary_, options_, as_)
14
+ end
15
+
16
+ def column(name_, type_, options_={})
17
+ if (info_ = @base.spatial_column_constructor(type_.to_sym))
18
+ type_ = options_[:type] || info_[:type] || type_
19
+ if type_.to_s == 'geometry' &&
20
+ (options_[:no_constraints] ||
21
+ options_[:limit].is_a?(::Hash) && options_[:limit][:no_constraints])
22
+ then
23
+ options_.delete(:limit)
24
+ else
25
+ options_[:type] = type_
26
+ type_ = :spatial
27
+ end
28
+ end
29
+ if type_ == :spatial
30
+ if (limit_ = options_.delete(:limit))
31
+ options_.merge!(limit_) if limit_.is_a?(::Hash)
32
+ end
33
+ if options_[:geographic]
34
+ type_ = :geography
35
+ spatial_type_ = (options_[:type] || 'geometry').to_s.upcase.gsub('_', '')
36
+ spatial_type_ << 'Z' if options_[:has_z]
37
+ spatial_type_ << 'M' if options_[:has_m]
38
+ options_[:limit] = "#{spatial_type_},#{options_[:srid] || 4326}"
39
+ end
40
+ name_ = name_.to_s
41
+ if primary_key_column_name == name_
42
+ raise ArgumentError, "you can't redefine the primary key column '#{name_}'. To define a custom primary key, pass { id: false } to create_table."
43
+ end
44
+ col_ = new_column_definition(name_, type_, options_)
45
+ col_.set_spatial_type(options_[:type])
46
+ col_.set_geographic(options_[:geographic])
47
+ col_.set_srid(options_[:srid])
48
+ col_.set_has_z(options_[:has_z])
49
+ col_.set_has_m(options_[:has_m])
50
+ (col_.geographic? ? @columns_hash : @spatial_columns_hash)[name_] = col_
51
+ else
52
+ super(name_, type_, options_)
53
+ end
54
+ self
55
+ end
56
+
57
+ def create_column_definition(name_, type_)
58
+ if type_ == :spatial || type_ == :geography
59
+ PostGISAdapter::ColumnDefinition.new(name_, type_)
60
+ else
61
+ super
62
+ end
63
+ end
64
+
65
+ def non_geographic_spatial_columns
66
+ @spatial_columns_hash.values
67
+ end
68
+
69
+ end
70
+
71
+
72
+ class ColumnDefinition < ConnectionAdapters::ColumnDefinition # :nodoc:
73
+
74
+ def spatial_type
75
+ @spatial_type
76
+ end
77
+
78
+ def geographic?
79
+ @geographic
80
+ end
81
+
82
+ def srid
83
+ @srid ? @srid.to_i : (geographic? ? 4326 : -1)
84
+ end
85
+
86
+ def has_z?
87
+ @has_z
88
+ end
89
+
90
+ def has_m?
91
+ @has_m
92
+ end
93
+
94
+ def set_geographic(value_)
95
+ @geographic = value_ ? true : false
96
+ end
97
+
98
+ def set_spatial_type(value_)
99
+ @spatial_type = value_.to_s
100
+ end
101
+
102
+ def set_srid(value_)
103
+ @srid = value_
104
+ end
105
+
106
+ def set_has_z(value_)
107
+ @has_z = value_ ? true : false
108
+ end
109
+
110
+ def set_has_m(value_)
111
+ @has_m = value_ ? true : false
112
+ end
113
+
114
+ end
115
+
116
+
117
+ end
118
+
119
+ end
120
+
121
+ end
@@ -0,0 +1,3 @@
1
+ require 'rails/railtie'
2
+ require 'active_record/connection_adapters/postgis_adapter'
3
+ load ::File.expand_path('shared/railtie.rb', ::File.dirname(__FILE__))
@@ -0,0 +1,23 @@
1
+ module Arel # :nodoc:
2
+ module Visitors # :nodoc:
3
+
4
+ class PostGIS < PostgreSQL # :nodoc:
5
+
6
+ FUNC_MAP = {
7
+ 'st_wkttosql' => 'ST_GeomFromEWKT',
8
+ }
9
+
10
+ include ::RGeo::ActiveRecord::SpatialToSql
11
+
12
+ def st_func(standard_name_)
13
+ FUNC_MAP[standard_name_.downcase] || standard_name_
14
+ end
15
+
16
+ alias_method :visit_in_spatial_context, :visit
17
+
18
+ end
19
+
20
+ VISITORS['postgis'] = ::Arel::Visitors::PostGIS
21
+
22
+ end
23
+ end
@@ -0,0 +1,46 @@
1
+ module ActiveRecord # :nodoc:
2
+ module ConnectionAdapters # :nodoc:
3
+ module PostGISAdapter # :nodoc:
4
+ SPATIAL_COLUMN_CONSTRUCTORS = ::RGeo::ActiveRecord::DEFAULT_SPATIAL_COLUMN_CONSTRUCTORS.merge(
5
+ :geography => {:type => 'geometry', :geographic => true}
6
+ )
7
+
8
+ module CommonAdapterMethods # :nodoc:
9
+ def set_rgeo_factory_settings(factory_settings_)
10
+ @rgeo_factory_settings = factory_settings_
11
+ end
12
+
13
+ def adapter_name
14
+ PostGISAdapter::ADAPTER_NAME
15
+ end
16
+
17
+ def spatial_column_constructor(name_)
18
+ PostGISAdapter::SPATIAL_COLUMN_CONSTRUCTORS[name_]
19
+ end
20
+
21
+ def postgis_lib_version
22
+ @postgis_lib_version ||= select_value("SELECT PostGIS_Lib_Version()")
23
+ end
24
+
25
+ # http://postgis.17.x6.nabble.com/Default-SRID-td5001115.html
26
+ def default_srid
27
+ 0
28
+ end
29
+
30
+ def srs_database_columns
31
+ {:srtext_column => 'srtext', :proj4text_column => 'proj4text', :auth_name_column => 'auth_name', :auth_srid_column => 'auth_srid'}
32
+ end
33
+
34
+ def quote(value_, column_=nil)
35
+ if ::RGeo::Feature::Geometry.check_type(value_)
36
+ "'#{::RGeo::WKRep::WKBGenerator.new(:hex_format => true, :type_format => :ewkb, :emit_ewkb_srid => true).generate(value_)}'"
37
+ elsif value_.is_a?(::RGeo::Cartesian::BoundingBox)
38
+ "'#{value_.min_x},#{value_.min_y},#{value_.max_x},#{value_.max_y}'::box"
39
+ else
40
+ super
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ unless defined?(::ActiveRecord::ConnectionAdapters::PostGISAdapter::Railtie)
2
+ module ActiveRecord # :nodoc:
3
+ module ConnectionAdapters # :nodoc:
4
+ module PostGISAdapter # :nodoc:
5
+ class Railtie < ::Rails::Railtie # :nodoc:
6
+ rake_tasks do
7
+ load ::File.expand_path("../rails4/databases.rake", ::File.dirname(__FILE__))
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveRecord # :nodoc:
2
+
3
+ module ConnectionAdapters # :nodoc:
4
+
5
+ module PostGISAdapter # :nodoc:
6
+
7
+
8
+ def self.initial_setup
9
+ gis_ignore_tables_ = ['geometry_columns', 'spatial_ref_sys', 'layer', 'topology']
10
+ ignore_tables_ = ::ActiveRecord::SchemaDumper.ignore_tables
11
+ gis_ignore_tables_.each do |table_|
12
+ ignore_tables_ << table_ unless ignore_tables_.include?(table_)
13
+ end
14
+ end
15
+
16
+
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,7 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module PostGISAdapter
4
+ VERSION = "0.7.0".freeze
5
+ end
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ require 'active_record/connection_adapters/postgis_adapter.rb'
data/test/database.yml ADDED
@@ -0,0 +1,5 @@
1
+ adapter: postgis
2
+ host: 127.0.0.1
3
+ database: postgis_adapter_test
4
+ username: postgres
5
+ setup: default
data/test/tc_basic.rb ADDED
@@ -0,0 +1,212 @@
1
+ require 'minitest/autorun'
2
+ require 'rgeo/active_record/adapter_test_helper'
3
+
4
+
5
+ module RGeo
6
+ module ActiveRecord # :nodoc:
7
+ module PostGISAdapter # :nodoc:
8
+ module Tests # :nodoc:
9
+
10
+ class TestBasic < ::MiniTest::Test # :nodoc:
11
+
12
+ DATABASE_CONFIG_PATH = ::File.dirname(__FILE__)+'/database.yml'
13
+ OVERRIDE_DATABASE_CONFIG_PATH = ::File.dirname(__FILE__)+'/database_local.yml'
14
+
15
+ include AdapterTestHelper
16
+
17
+ define_test_methods do
18
+
19
+
20
+ def populate_ar_class(content_)
21
+ klass_ = create_ar_class
22
+ case content_
23
+ when :mercator_point
24
+ klass_.connection.create_table(:spatial_test) do |t_|
25
+ t_.column 'latlon', :point, :srid => 3785
26
+ end
27
+ when :latlon_point_geographic
28
+ klass_.connection.create_table(:spatial_test) do |t_|
29
+ t_.column 'latlon', :point, :srid => 4326, :geographic => true
30
+ end
31
+ when :no_constraints
32
+ klass_.connection.create_table(:spatial_test) do |t_|
33
+ t_.column 'geo', :geometry, :no_constraints => true
34
+ end
35
+ end
36
+ klass_
37
+ end
38
+
39
+
40
+ def test_version
41
+ refute_nil(::ActiveRecord::ConnectionAdapters::PostGISAdapter::VERSION)
42
+ end
43
+
44
+
45
+ def test_postgis_available
46
+ connection_ = create_ar_class.connection
47
+ assert_equal('PostGIS', connection_.adapter_name)
48
+ refute_nil(connection_.postgis_lib_version)
49
+ end
50
+
51
+
52
+ def test_set_and_get_point
53
+ klass_ = populate_ar_class(:mercator_point)
54
+ obj_ = klass_.new
55
+ assert_nil(obj_.latlon)
56
+ obj_.latlon = @factory.point(1.0, 2.0)
57
+ assert_equal(@factory.point(1.0, 2.0), obj_.latlon)
58
+ assert_equal(3785, obj_.latlon.srid)
59
+ end
60
+
61
+
62
+ def test_set_and_get_point_from_wkt
63
+ klass_ = populate_ar_class(:mercator_point)
64
+ obj_ = klass_.new
65
+ assert_nil(obj_.latlon)
66
+ obj_.latlon = 'POINT(1 2)'
67
+ assert_equal(@factory.point(1.0, 2.0), obj_.latlon)
68
+ assert_equal(3785, obj_.latlon.srid)
69
+ end
70
+
71
+
72
+ def test_save_and_load_point
73
+ klass_ = populate_ar_class(:mercator_point)
74
+ obj_ = klass_.new
75
+ obj_.latlon = @factory.point(1.0, 2.0)
76
+ obj_.save!
77
+ id_ = obj_.id
78
+ obj2_ = klass_.find(id_)
79
+ assert_equal(@factory.point(1.0, 2.0), obj2_.latlon)
80
+ assert_equal(3785, obj2_.latlon.srid)
81
+ assert_equal(true, ::RGeo::Geos.is_geos?(obj2_.latlon))
82
+ end
83
+
84
+
85
+ def test_save_and_load_geographic_point
86
+ klass_ = populate_ar_class(:latlon_point_geographic)
87
+ obj_ = klass_.new
88
+ obj_.latlon = @factory.point(1.0, 2.0)
89
+ obj_.save!
90
+ id_ = obj_.id
91
+ obj2_ = klass_.find(id_)
92
+ assert_equal(@geographic_factory.point(1.0, 2.0), obj2_.latlon)
93
+ assert_equal(4326, obj2_.latlon.srid)
94
+ assert_equal(false, ::RGeo::Geos.is_geos?(obj2_.latlon))
95
+ end
96
+
97
+
98
+ def test_save_and_load_point_from_wkt
99
+ klass_ = populate_ar_class(:mercator_point)
100
+ obj_ = klass_.new
101
+ obj_.latlon = 'POINT(1 2)'
102
+ obj_.save!
103
+ id_ = obj_.id
104
+ obj2_ = klass_.find(id_)
105
+ assert_equal(@factory.point(1.0, 2.0), obj2_.latlon)
106
+ assert_equal(3785, obj2_.latlon.srid)
107
+ end
108
+
109
+
110
+ def test_set_point_bad_wkt
111
+ klass_ = populate_ar_class(:mercator_point)
112
+ obj_ = klass_.create(:latlon => 'POINT (x)')
113
+ assert_nil(obj_.latlon)
114
+ end
115
+
116
+
117
+ def test_set_point_wkt_wrong_type
118
+ klass_ = populate_ar_class(:mercator_point)
119
+ assert_raises(::ActiveRecord::StatementInvalid) do
120
+ klass_.create(:latlon => 'LINESTRING(1 2, 3 4, 5 6)')
121
+ end
122
+ end
123
+
124
+
125
+ def test_custom_factory
126
+ klass_ = create_ar_class
127
+ klass_.connection.create_table(:spatial_test) do |t_|
128
+ t_.point(:latlon, :srid => 4326)
129
+ end
130
+ factory_ = ::RGeo::Geographic.simple_mercator_factory
131
+ klass_.class_eval do
132
+ set_rgeo_factory_for_column(:latlon, factory_)
133
+ end
134
+ rec_ = klass_.new
135
+ rec_.latlon = 'POINT(-122 47)'
136
+ assert_equal(factory_, rec_.latlon.factory)
137
+ rec_.save!
138
+ assert_equal(factory_, rec_.latlon.factory)
139
+ rec2_ = klass_.find(rec_.id)
140
+ assert_equal(factory_, rec2_.latlon.factory)
141
+ end
142
+
143
+
144
+ def test_readme_example
145
+ klass_ = create_ar_class
146
+ klass_.connection.create_table(:spatial_test) do |t_|
147
+ t_.column(:shape, :geometry)
148
+ t_.line_string(:path, :srid => 3785)
149
+ t_.point(:latlon, :geographic => true)
150
+ end
151
+ klass_.connection.change_table(:spatial_test) do |t_|
152
+ t_.index(:latlon, :spatial => true)
153
+ end
154
+ klass_.class_eval do
155
+ self.rgeo_factory_generator = ::RGeo::Geos.method(:factory)
156
+ set_rgeo_factory_for_column(:latlon, ::RGeo::Geographic.spherical_factory)
157
+ end
158
+ rec_ = klass_.new
159
+ rec_.latlon = 'POINT(-122 47)'
160
+ loc_ = rec_.latlon
161
+ assert_equal(47, loc_.latitude)
162
+ rec_.shape = loc_
163
+ assert_equal(true, ::RGeo::Geos.is_geos?(rec_.shape))
164
+ end
165
+
166
+
167
+ # no_constraints no longer supported in PostGIS 2.0
168
+ def _test_save_and_load_no_constraints
169
+ klass_ = populate_ar_class(:no_constraints)
170
+ factory1_ = ::RGeo::Cartesian.preferred_factory(:srid => 3785)
171
+ factory2_ = ::RGeo::Cartesian.preferred_factory(:srid => 2000)
172
+ obj_ = klass_.new
173
+ obj_.geo = factory1_.point(1.0, 2.0)
174
+ obj_.save!
175
+ id_ = obj_.id
176
+ obj2_ = klass_.find(id_)
177
+ assert_equal(factory1_.point(1.0, 2.0), obj2_.geo)
178
+ assert_equal(3785, obj2_.geo.srid)
179
+ obj2_.geo = factory2_.point(3.0, 4.0)
180
+ obj2_.save!
181
+ obj3_ = klass_.find(id_)
182
+ assert_equal(factory2_.point(3.0, 4.0), obj3_.geo)
183
+ assert_equal(2000, obj3_.geo.srid)
184
+ end
185
+
186
+
187
+ def test_point_to_json
188
+ klass_ = populate_ar_class(:mercator_point)
189
+ obj_ = klass_.new
190
+ assert_match(/"latlon":null/, obj_.to_json)
191
+ obj_.latlon = @factory.point(1.0, 2.0)
192
+ assert_match(/"latlon":"POINT\s\(1\.0\s2\.0\)"/, obj_.to_json)
193
+ end
194
+
195
+
196
+ def test_custom_column
197
+ klass_ = populate_ar_class(:mercator_point)
198
+ rec_ = klass_.new
199
+ rec_.latlon = 'POINT(0 0)'
200
+ rec_.save
201
+ refute_nil(klass_.select("CURRENT_TIMESTAMP as ts").first.ts)
202
+ end
203
+
204
+
205
+ end
206
+
207
+ end
208
+
209
+ end
210
+ end
211
+ end
212
+ end