gotime-postgis_adapter 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ gem "pg"
4
+ gem "nofxx-georuby"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", "~> 2.3.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "rcov", ">= 0"
12
+ gem "autotest"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,31 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ ZenTest (4.5.0)
5
+ autotest (4.4.6)
6
+ ZenTest (>= 4.4.1)
7
+ diff-lcs (1.1.2)
8
+ json_pure (1.4.6)
9
+ nofxx-georuby (1.9.0)
10
+ json_pure (>= 1.4.6)
11
+ pg (0.10.1)
12
+ rcov (0.9.9)
13
+ rspec (2.3.0)
14
+ rspec-core (~> 2.3.0)
15
+ rspec-expectations (~> 2.3.0)
16
+ rspec-mocks (~> 2.3.0)
17
+ rspec-core (2.3.1)
18
+ rspec-expectations (2.3.0)
19
+ diff-lcs (~> 1.1.2)
20
+ rspec-mocks (2.3.0)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ autotest
27
+ bundler (~> 1.0.0)
28
+ nofxx-georuby
29
+ pg
30
+ rcov
31
+ rspec (~> 2.3.0)
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2008-12-10
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Spatial Adapter Copyright (c) 2006 Guilhem Vellut <guilhem.vellut+georuby@gmail.com>
2
+ PostGis Adapter Functions (c) 2008 Marcos Piccinini <nofxx>
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,380 @@
1
+ = PostgisAdapter
2
+
3
+ A plugin for ActiveRecord which manages the PostGIS geometric columns
4
+ in a transparent way (that is like the other base data type columns).
5
+ It also provides a way to manage these columns in migrations.
6
+
7
+ This fork adds handy methods to make geometrical calculations on postgis.
8
+ Based on http://georuby.rubyforge.org Spatial Adapter
9
+
10
+ RDocs - http://docs.github.com/nofxx/postgis_adapter
11
+ Postgis Online reference - http://postgis.refractions.net
12
+ Postgis Manual - http://postgis.refractions.net/documentation/manual-svn
13
+
14
+
15
+ == Install
16
+
17
+ If you are using Spatial Adapter, *remove it first*.
18
+
19
+ gem install postgis_adapter
20
+
21
+
22
+ === Dependencies
23
+
24
+ - georuby gem
25
+ - postgres 8.3+
26
+ - postgis 1.3+
27
+
28
+
29
+ === Rails 3+
30
+
31
+ Add dependency to Gemfile:
32
+
33
+ gem "postgis_adapter"
34
+
35
+
36
+ Or, to use latest from repository:
37
+
38
+ gem "postgis_adapter", :git => 'git://github.com/nofxx/postgis_adapter.git'
39
+
40
+
41
+ === Rails 2
42
+
43
+ gem install postgis_adapter -v 0.7.8
44
+
45
+
46
+ == How to Use
47
+
48
+ Geometric columns in your ActiveRecord models now appear just like
49
+ any other column of other basic data types. They can also be dumped
50
+ in ruby schema mode and loaded in migrations the same way as columns
51
+ of basic types.
52
+
53
+
54
+ === Example App
55
+
56
+ Simple rails app to demonstrate, check it out:
57
+
58
+ http://github.com/nofxx/postgis_example
59
+
60
+
61
+ === Model
62
+
63
+ class TablePoint < ActiveRecord::Base
64
+ end
65
+
66
+ That was easy! As you see, there is no need to declare a column as geometric.
67
+ The plugin will get this information by itself.
68
+
69
+ Here is an example of PostGIS row creation and access, using the
70
+ model and the table defined above :
71
+
72
+ pt = TablePoint.new(:data => "Hello!",:geom => Point.from_x_y(1,2))
73
+ pt.save
74
+ pt = TablePoint.first
75
+ puts pt.geom.x
76
+ => 1
77
+
78
+
79
+ == PostGIS Functions
80
+
81
+ Here are this fork additions. To use it:
82
+
83
+ acts_as_geom [column_name] => [geom_type]
84
+
85
+
86
+ Examples:
87
+
88
+ class POI < ActiveRecord::Base
89
+ acts_as_geom :geom => :point
90
+ end
91
+
92
+ class Street < ActiveRecord::Base
93
+ acts_as_geom :line => :line_string
94
+ end
95
+
96
+ ...
97
+
98
+
99
+
100
+ == Play!
101
+
102
+ @place = Poi.new( :geom => Point.from_x_y(10,20) )
103
+ @park = Park.new( :area => **Polygon** )
104
+ @street = Street.new( :line => **LineString** )
105
+
106
+ @place.inside?(@park)
107
+ => true
108
+
109
+ @place.in_bounds?(@park, 0.5) # margin
110
+ => false
111
+
112
+ @place.outside?(@park)
113
+ @street.crosses?(@park)
114
+ @area.contains?(@place)
115
+ ...
116
+
117
+
118
+ === Polygons:
119
+
120
+ @park.area
121
+ => 1345
122
+
123
+ @park.contains?(@point)
124
+ => true
125
+
126
+ @park.overlaps?(@other_park)
127
+ => false
128
+
129
+ Supports transform (useful to transform SRID to UTM for area in Km^2)
130
+
131
+ @park.area(SRID)
132
+ => Area with new SRID
133
+
134
+
135
+ === LineStrings:
136
+
137
+ @street_east.intersects?(@street_west)
138
+ => false
139
+
140
+ @street_central.length
141
+ => 4508.53636
142
+
143
+ @street.length_spheroid
144
+ => 4.40853636
145
+
146
+
147
+ === Class Methods
148
+
149
+ City.close_to(@point)
150
+ => [Array of cities in order by distance...
151
+
152
+ Street.close_to(@point)
153
+ => [Array streets in order by distance...
154
+
155
+ Country.contain(@point)
156
+ => The Conutry that contains the point
157
+
158
+ Area.contains(@point)
159
+ => [Array of areas contains the point...
160
+
161
+
162
+ === BBox Support
163
+
164
+ @area.strictly_left_of? @point
165
+
166
+ @area.overlaps_or_above? @street
167
+
168
+ ...
169
+
170
+ completely_contained_by?
171
+ completely_contains?
172
+ overlaps_or_above?
173
+ overlaps_or_below?
174
+ overlaps_or_left_of?
175
+ overlaps_or_right_of?
176
+ strictly_above?
177
+ strictly_below?
178
+ strictly_left_of?
179
+ strictly_right_of?
180
+ interacts_with?
181
+ binary_equal?
182
+ same_as?
183
+
184
+
185
+ Or use a (almost) PostGIS like notation:
186
+
187
+ @area.bbox "<<", @point
188
+
189
+ @area.bbox "|>>", @point
190
+
191
+ @area.bbox "@", @park
192
+
193
+
194
+ === Warning
195
+
196
+ *To be fixed:*
197
+
198
+ This only supports one geom column per model. Still looking for the best way to
199
+ implement a multi geom.
200
+
201
+ http://nofxx.lighthouseapp.com/projects/20712/tickets/3-multiple-geoms-in-model
202
+
203
+
204
+ === Find_by
205
+
206
+ find_by_*column* has been redefined when column is of a geometric type.
207
+ Instead of using the Rails default '=' operator, for which I can't see
208
+ a definition for MySql spatial datatypes and which performs a bounding
209
+ box equality test in PostGIS, it uses a bounding box intersection:
210
+ && in PostGIS and MBRIntersects in MySQL, which can both make use
211
+ of a spatial index if one is present to speed up the queries.
212
+ You could use this query, for example, if you need to display data
213
+ from the database: You would want only the geometries which are in
214
+ the screen rectangle and you could use a bounding box query for that.
215
+ Since this is a common case, it is the default. You have 2 ways to use
216
+ the find_by_*geom_column*: Either by passing a geometric object directly,
217
+ or passing an array with the 2 opposite corners of a bounding box
218
+ (with 2 or 3 coordinates depending of the dimension of the data).
219
+
220
+ Park.find_by_geom(LineString.from_coordinates([[1.4,5.6],[2.7,8.9],[1.6,5.6]]))
221
+
222
+ or
223
+
224
+ Park.find_by_geom([[3,5.6],[19.98,5.9]])
225
+
226
+ In PostGIS, since you can only use operations with geometries with the same SRID, you can add a third element representing the SRID of the bounding box to the array. It is by default set to -1:
227
+
228
+ Park.find_by_geom([[3,5.6],[19.98,5.9],123])
229
+
230
+
231
+
232
+ == Database Tools
233
+
234
+ === Migrations
235
+
236
+ Here is an example of code for the creation of a table with a
237
+ geometric column in PostGIS, along with the addition of a spatial
238
+ index on the column :
239
+
240
+ ActiveRecord::Schema.define do
241
+ create_table :places do |t|
242
+ t.string :name
243
+ t.point :geom, :srid => 4326, :with_z => true, :null => false
244
+
245
+ t.timestamps
246
+ end
247
+
248
+ add_index :places, :geom, :spatial => true
249
+ end
250
+
251
+
252
+ Types:
253
+
254
+ point
255
+ polygon
256
+ line_string
257
+ multi_point
258
+ multi_polygon
259
+ multi_line_string
260
+ geometry
261
+ geometry_collection
262
+
263
+
264
+ === PostGIS Helper Scripts
265
+
266
+ Optional, this will create postgis enabled database automatically for you.
267
+
268
+ Helpers to create postgis template database. At time of writing,
269
+ postgis.sql and spatial_ref_sys.sql are used.
270
+
271
+
272
+ ==== System wide
273
+
274
+
275
+ Find where your OS put those sql files and:
276
+
277
+ rake postgis:template path/to/sqls/folder
278
+
279
+
280
+ ==== Vendorize
281
+
282
+ Place the following scripts in a folder named 'spatial' under the 'db' folder; For example:
283
+
284
+ RAILS_ROOT/db/spatial/lwpostgis.sql
285
+ RAILS_ROOT/db/spatial/spatial_ref_sys
286
+
287
+ These will be used when creating the Test database when running the Rake Test tasks.
288
+ These scripts should have been installed when the PostGIS libraries were installed.
289
+ Online reference: http://postgis.refractions.net/
290
+
291
+
292
+ === Fixtures
293
+
294
+ If you use fixtures for your unit tests, at some point,
295
+ you will want to input a geometry. You could transform your
296
+ geometries to a form suitable for YAML yourself everytime but
297
+ the spatial adapter provides a method to do it for you: +to_yaml+.
298
+ It works for both MySQL and PostGIS (although the string returned
299
+ is different for each database). You would use it like this, if
300
+ the geometric column is a point:
301
+
302
+ fixture:
303
+ id: 1
304
+ data: HELLO
305
+ geom: <%= Point.from_x_y(123.5,321.9).to_yaml %>
306
+
307
+
308
+ === Annotate
309
+
310
+ If you are using annotate_models, check out this fork which adds geometrical annotations for PostgisAdapter and SpatialAdapter:
311
+
312
+ http://github.com/nofxx/annotate_models
313
+
314
+
315
+ == Geometric data types
316
+
317
+ Ruby geometric datatypes are currently made available only through
318
+ the GeoRuby library (http://georuby.rubyforge.org): This is where the
319
+ *Point.from_x_y* in the example above comes from. It is a goal
320
+ of a future release of the Spatial Adapter to support additional
321
+ geometric datatype libraries, such as Ruby/GEOS, as long as they
322
+ can support reading and writing of EWKB.
323
+
324
+
325
+
326
+ === Warning
327
+
328
+ - Since ActiveRecord seems to keep only the string values directly
329
+ returned from the database, it translates from these to the correct
330
+ types everytime an attribute is read, which is probably ok for simple
331
+ types, but might be less than efficient for geometries, since the EWKB
332
+ string has to be parsed everytime. Also it means you cannot modify the
333
+ geometry object returned from an attribute directly :
334
+
335
+ place = Place.first
336
+ place.the_geom.y=123456.7
337
+
338
+ - Since the translation to a geometry is performed everytime the_geom
339
+ is read, the change to y will not be saved! You would have to do
340
+ something like this :
341
+
342
+ place = Place.first
343
+ the_geom = place.the_geom
344
+ the_geom.y=123456.7
345
+ place.the_geom = the_geom
346
+
347
+
348
+ == Postgis Adapter
349
+
350
+ Marcos Piccinini (nofxx)
351
+ Ying Tsen Hong (tsenying)
352
+ Simon Tokumine (tokumine)
353
+ Fernando Blat (ferblape)
354
+ Shoaib Burq (sabman)
355
+
356
+ (in order of appearance)
357
+
358
+
359
+ == License
360
+
361
+ Spatial Adapter for Rails is released under the MIT license.
362
+ Postgis Adapter is released under the MIT license.
363
+
364
+
365
+ == Support
366
+
367
+ Tested using activerecord 3+ / postgresql 8.5+ / postgis 1.5+ / linux / osx
368
+
369
+ Any questions, enhancement proposals, bug notifications or corrections:
370
+
371
+
372
+ === PostgisAdapter
373
+
374
+ http://github.com/nofxx/postgis_adapter/issues
375
+
376
+
377
+ === SpatialAdapter
378
+
379
+ http://georuby.rubyforge.org
380
+ guilhem.vellut+georuby@gmail.com.
data/Rakefile ADDED
@@ -0,0 +1,70 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/rdoctask'
5
+ #require 'spec/rake/spectask'
6
+
7
+ CLEAN.include('**/*.gem')
8
+
9
+ namespace :gem do
10
+ desc "Create the postgis_adapter gem"
11
+ task :create => [:clean] do
12
+ spec = eval(IO.read('postgis_adapter.gemspec'))
13
+ Gem::Builder.new(spec).build
14
+ end
15
+
16
+ desc "Install the postgis_adapter gem"
17
+ task :install => [:create] do
18
+ file = Dir['*.gem'].first
19
+ sh "gem install #{file}"
20
+ end
21
+ end
22
+
23
+ # Spec::Rake::SpecTask.new(:spec) do |spec|
24
+ # spec.libs << 'lib' << 'spec'
25
+ # spec.spec_files = FileList['spec/**/*_spec.rb']
26
+ # end
27
+
28
+ # Spec::Rake::SpecTask.new(:rcov) do |spec|
29
+ # spec.libs << 'lib' << 'spec'
30
+ # spec.pattern = 'spec/**/*_spec.rb'
31
+ # spec.rcov = true
32
+ # end
33
+
34
+ Rake::RDocTask.new do |rdoc|
35
+ version = File.exist?('VERSION') ? File.read('VERSION').chomp : ""
36
+ rdoc.rdoc_dir = 'rdoc'
37
+ rdoc.title = "postgis_adapter #{version}"
38
+ rdoc.rdoc_files.include('README*')
39
+ rdoc.rdoc_files.include('lib/**/*.rb')
40
+ end
41
+
42
+ task :default => :spec
43
+
44
+ #
45
+ # Reek & Roodi
46
+ #
47
+ begin
48
+ require 'reek/rake_task'
49
+ Reek::RakeTask.new do |t|
50
+ t.fail_on_error = true
51
+ t.verbose = false
52
+ t.source_files = 'lib/**/*.rb'
53
+ end
54
+ rescue LoadError
55
+ task :reek do
56
+ abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
57
+ end
58
+ end
59
+
60
+ begin
61
+ require 'roodi'
62
+ require 'roodi_task'
63
+ RoodiTask.new do |t|
64
+ t.verbose = false
65
+ end
66
+ rescue LoadError
67
+ task :roodi do
68
+ abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
69
+ end
70
+ end
@@ -0,0 +1,43 @@
1
+ #
2
+ # PostGIS Adapter
3
+ #
4
+ # http://github.com/nofxx/postgis_adapter
5
+ #
6
+ module PostgisAdapter
7
+ module Functions
8
+ def self.included(base)
9
+ base.send :extend, ClassMethods
10
+ end
11
+
12
+ module ClassMethods
13
+
14
+ # has_geom :db_field => :geom_type
15
+ # Examples:
16
+ #
17
+ # has_geom :data => :point
18
+ # has_geom :geom => :line_string
19
+ # has_geom :geom => :polygon
20
+ #
21
+ def has_geom(*geom)
22
+ cattr_accessor :postgis_geoms
23
+ self.postgis_geoms = geom[0] # {:columns => column
24
+ send :include, case geom[0].values[0]
25
+ when :point then PointFunctions
26
+ when :polygon then PolygonFunctions
27
+ when :line_string, :multi_line_string then LineStringFunctions
28
+ when :multi_polygon then MultiPolygonFunctions
29
+ end unless geom[0].kind_of? Symbol
30
+ end
31
+ alias :acts_as_geom :has_geom
32
+
33
+ def get_geom_type(column)
34
+ self.postgis_geoms.values[0] rescue nil
35
+ # self.columns.select { |c| c.name == column.to_s }[0].geometry_type
36
+ # rescue ActiveRecord::StatementInvalid => e
37
+ # nil
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ ActiveRecord::Base.send :include, PostgisAdapter::Functions
@@ -0,0 +1,105 @@
1
+ #
2
+ # PostGIS Adapter
3
+ #
4
+ # Common Spatial Adapter for ActiveRecord
5
+ #
6
+ # Code from
7
+ # http://georuby.rubyforge.org Spatial Adapter
8
+ #
9
+
10
+ #Addition of a flag indicating if the index is spatial
11
+ ActiveRecord::ConnectionAdapters::IndexDefinition.class_eval do
12
+ attr_accessor :spatial
13
+
14
+ def initialize(table, name, unique, spatial,columns)
15
+ super(table,name,unique,columns)
16
+ @spatial = spatial
17
+ end
18
+
19
+ end
20
+
21
+ module SpatialAdapter
22
+ #Translation of geometric data types
23
+ def geometry_data_types
24
+ {
25
+ :point => { :name => "POINT" },
26
+ :line_string => { :name => "LINESTRING" },
27
+ :polygon => { :name => "POLYGON" },
28
+ :geometry_collection => { :name => "GEOMETRYCOLLECTION" },
29
+ :multi_point => { :name => "MULTIPOINT" },
30
+ :multi_line_string => { :name => "MULTILINESTRING" },
31
+ :multi_polygon => { :name => "MULTIPOLYGON" },
32
+ :geometry => { :name => "GEOMETRY"}
33
+ }
34
+ end
35
+
36
+ end
37
+
38
+
39
+ #using a mixin instead of subclassing Column since each adapter can have a specific subclass of Column
40
+ module SpatialColumn
41
+ attr_reader :geometry_type, :srid, :with_z, :with_m
42
+
43
+ def initialize(name, default, sql_type = nil, null = true,srid=-1,with_z=false,with_m=false)
44
+ super(name,default,sql_type,null)
45
+ @geometry_type = geometry_simplified_type(@sql_type)
46
+ @srid = srid
47
+ @with_z = with_z
48
+ @with_m = with_m
49
+ end
50
+
51
+
52
+ #Redefines type_cast to add support for geometries
53
+ def type_cast(value)
54
+ return nil if value.nil?
55
+ case type
56
+ when :geometry then self.class.string_to_geometry(value)
57
+ else super
58
+ end
59
+ end
60
+
61
+ #Redefines type_cast_code to add support for geometries.
62
+ #
63
+ #WARNING : Since ActiveRecord keeps only the string values directly returned from the database, it translates from these to the correct types everytime an attribute is read (using the code returned by this method), which is probably ok for simple types, but might be less than efficient for geometries. Also you cannot modify the geometry object returned directly or your change will not be saved.
64
+ def type_cast_code(var_name)
65
+ case type
66
+ when :geometry then "#{self.class.name}.string_to_geometry(#{var_name})"
67
+ else super
68
+ end
69
+ end
70
+
71
+
72
+ #Redefines klass to add support for geometries
73
+ def klass
74
+ case type
75
+ when :geometry then GeoRuby::SimpleFeatures::Geometry
76
+ else super
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ #Redefines the simplified_type method to add behaviour for when a column is of type geometry
83
+ def simplified_type(field_type)
84
+ case field_type
85
+ when /geometry|point|linestring|polygon|multipoint|multilinestring|multipolygon|geometrycollection/i then :geometry
86
+ else super
87
+ end
88
+ end
89
+
90
+ #less simlpified geometric type to be use in migrations
91
+ def geometry_simplified_type(field_type)
92
+ case field_type
93
+ when /^point$/i then :point
94
+ when /^linestring$/i then :line_string
95
+ when /^polygon$/i then :polygon
96
+ when /^geometry$/i then :geometry
97
+ when /multipoint/i then :multi_point
98
+ when /multilinestring/i then :multi_line_string
99
+ when /multipolygon/i then :multi_polygon
100
+ when /geometrycollection/i then :geometry_collection
101
+ end
102
+ end
103
+
104
+
105
+ end