postgis_adapter 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
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/Manifest.txt ADDED
@@ -0,0 +1,36 @@
1
+ History.txt
2
+ MIT-LICENSE
3
+ Manifest.txt
4
+ README.rdoc
5
+ Rakefile
6
+ init.rb
7
+ install.rb
8
+ lib/postgis_adapter.rb
9
+ lib/postgis_adapter/acts_as_geom.rb
10
+ lib/postgis_adapter/common_spatial_adapter.rb
11
+ lib/postgis_functions.rb
12
+ lib/postgis_functions/bbox.rb
13
+ lib/postgis_functions/class.rb
14
+ lib/postgis_functions/common.rb
15
+ lib/postgis_functions/linestring.rb
16
+ lib/postgis_functions/point.rb
17
+ lib/postgis_functions/polygon.rb
18
+ postgis_adapter.gemspec
19
+ rails/init.rb
20
+ script/console
21
+ script/destroy
22
+ script/generate
23
+ spec/acts_as_geom_spec.rb
24
+ spec/common_spatial_adapter_spec.rb
25
+ spec/db/database_postgis.yml
26
+ spec/db/models_postgis.rb
27
+ spec/db/schema_postgis.rb
28
+ spec/postgis_adapter_spec.rb
29
+ spec/postgis_functions/bbox_spec.rb
30
+ spec/postgis_functions/linestring_spec.rb
31
+ spec/postgis_functions/point_spec.rb
32
+ spec/postgis_functions/polygon_spec.rb
33
+ spec/postgis_functions_spec.rb
34
+ spec/spec.opts
35
+ spec/spec_helper.rb
36
+ uninstall.rb
data/README.rdoc ADDED
@@ -0,0 +1,311 @@
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
+
9
+ Postgis Manual - http://postgis.refractions.net/documentation/manual-svn
10
+
11
+ *PostGIS and Rails 2+ only*.
12
+
13
+
14
+ === Install
15
+
16
+ If you are using Spatial Adapter, *remove it first*.
17
+
18
+
19
+ ==== Dependencies
20
+
21
+ - georuby
22
+ - postgres 8.3+
23
+ - postgis 1.3+
24
+
25
+
26
+ ==== As gem:
27
+
28
+ sudo gem sources --add http://gems.github.com
29
+ sudo gem install nofxx-postgis_adapter
30
+
31
+ config.gem "nofxx-postgis_adapter", :lib => "postgis_adapter", :source => "http://gems.github.com"
32
+
33
+
34
+ ==== As plugin:
35
+
36
+ script/plugin install git://github.com/nofxx/postgis_adapter.git
37
+
38
+
39
+ === How to Use
40
+
41
+ Geometric columns in your ActiveRecord models now appear just like
42
+ any other column of other basic data types. They can also be dumped
43
+ in ruby schema mode and loaded in migrations the same way as columns
44
+ of basic types.
45
+
46
+
47
+ === Model
48
+
49
+ class TablePoint < ActiveRecord::Base
50
+ end
51
+
52
+ That was easy! As you see, there is no need to declare a column as geometric.
53
+ The plugin will get this information by itself.
54
+
55
+ Here is an example of PostGIS row creation and access, using the
56
+ model and the table defined above :
57
+
58
+ pt = TablePoint.new(:data => "Hello!",:geom => Point.from_x_y(1,2))
59
+ pt.save
60
+ pt = TablePoint.first
61
+ puts pt.geom.x
62
+ => 1
63
+
64
+
65
+ == PostGIS Functions
66
+
67
+ Here are this fork additions. To use it:
68
+
69
+
70
+ class Street < ActiveRecord::Base
71
+ acts_as_geom :line
72
+ end
73
+
74
+ ...
75
+
76
+ @place = Poi.new( :data => **Point** )
77
+ @park = Park.new( :area => **Polygon** )
78
+ @street = Street.new( :line => **LineString** )
79
+
80
+
81
+ === Play!
82
+
83
+ @place.inside?(@park)
84
+ => true
85
+
86
+ @place.in_bounds?(@park, 0.5) # margin
87
+ => false
88
+
89
+ @place.outside?(@park)
90
+
91
+ @street.crosses?(@park)
92
+
93
+ @area.contains?(@place)
94
+
95
+
96
+ Polygons:
97
+
98
+ @park.area
99
+ => 1345
100
+
101
+ @park.contains?(@point)
102
+ => true
103
+
104
+ @park.overlaps?(@other_park)
105
+ => false
106
+
107
+
108
+ Line Strings:
109
+
110
+ @street_east.intersects?(@street_west)
111
+ => false
112
+
113
+ @street_central.length
114
+ => 4508.53636
115
+
116
+ @street_central.length(:miles)
117
+ => 2.81798593
118
+
119
+ @street.length_spheroid
120
+ => 4.40853636
121
+
122
+
123
+ === And for classes:
124
+
125
+ City.close_to(@point)
126
+ => [Array of cities in order by distance...
127
+
128
+ Street.close_to(@point)
129
+ => [Array streets in order by distance...
130
+
131
+ Country.contain(@point)
132
+ => The Conutry that contains the point
133
+
134
+ Areas.contains(@point)
135
+ => [Array of areas contains the point...
136
+
137
+
138
+ === BBox Support
139
+
140
+ @area.strictly_left_of? @point
141
+
142
+ @area.overlaps_or_above? @street
143
+
144
+ ...
145
+
146
+ completely_contained_by?
147
+ completely_contains?
148
+ overlaps_or_above?
149
+ overlaps_or_below?
150
+ overlaps_or_left_of?
151
+ overlaps_or_right_of?
152
+ strictly_above?
153
+ strictly_below?
154
+ strictly_left_of?
155
+ strictly_right_of?
156
+ interacts_with?
157
+ binary_equal?
158
+ same_as?
159
+
160
+
161
+ Or use a (almost) postgis like notation:
162
+
163
+ @area.bbox "<<", @point
164
+
165
+ @area.bbox "|>>", @point
166
+
167
+ @area.bbox "@", @park
168
+
169
+
170
+
171
+ === Warning
172
+
173
+ *To be fixed:*
174
+
175
+ This only supports one geom column per model. Still looking for the best way to
176
+ implement a multi geom.
177
+
178
+ http://nofxx.lighthouseapp.com/projects/20712/tickets/3-multiple-geoms-in-model
179
+
180
+
181
+ === Wiki
182
+
183
+ Check out the wiki pages (http://github.com/nofxx/postgis_adapter/wikis).
184
+ For all functions.
185
+
186
+
187
+ === Find_by
188
+
189
+ find_by_*column* has been redefined when column is of a geometric type.
190
+ Instead of using the Rails default '=' operator, for which I can't see
191
+ a definition for MySql spatial datatypes and which performs a bounding
192
+ box equality test in PostGIS, it uses a bounding box intersection:
193
+ && in PostGIS and MBRIntersects in MySQL, which can both make use
194
+ of a spatial index if one is present to speed up the queries.
195
+ You could use this query, for example, if you need to display data
196
+ from the database: You would want only the geometries which are in
197
+ the screen rectangle and you could use a bounding box query for that.
198
+ Since this is a common case, it is the default. You have 2 ways to use
199
+ the find_by_*geom_column*: Either by passing a geometric object directly,
200
+ or passing an array with the 2 opposite corners of a bounding box
201
+ (with 2 or 3 coordinates depending of the dimension of the data).
202
+
203
+ Park.find_by_geom(LineString.from_coordinates([[1.4,5.6],[2.7,8.9],[1.6,5.6]]))
204
+
205
+ or
206
+
207
+ Park.find_by_geom([[3,5.6],[19.98,5.9]])
208
+
209
+ 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:
210
+
211
+ Park.find_by_geom([[3,5.6],[19.98,5.9],123])
212
+
213
+
214
+
215
+ == Database Tools
216
+
217
+ === Migrations
218
+
219
+ Here is an example of code for the creation of a table with a
220
+ geometric column in PostGIS, along with the addition of a spatial
221
+ index on the column :
222
+
223
+ ActiveRecord::Schema.define do
224
+ create_table :places do |t|
225
+ t.string :name
226
+ t.point :geom, :srid => 123, :with_z => true, :null => false
227
+
228
+ t.timestamps
229
+ end
230
+ add_index :table_points, :geom, :spatial=>true
231
+ end
232
+
233
+
234
+ === Fixtures
235
+
236
+ If you use fixtures for your unit tests, at some point,
237
+ you will want to input a geometry. You could transform your
238
+ geometries to a form suitable for YAML yourself everytime but
239
+ the spatial adapter provides a method to do it for you: +to_yaml+.
240
+ It works for both MySQL and PostGIS (although the string returned
241
+ is different for each database). You would use it like this, if
242
+ the geometric column is a point:
243
+
244
+ fixture:
245
+ id: 1
246
+ data: HELLO
247
+ geom: <%= Point.from_x_y(123.5,321.9).to_yaml %>
248
+
249
+
250
+ === Annotate
251
+
252
+ If you are using annotate_models, check out this fork which adds geometrical annotations for PostgisAdapter and SpatialAdapter:
253
+
254
+ http://github.com/nofxx/annotate_models
255
+
256
+
257
+ == Geometric data types
258
+
259
+ Ruby geometric datatypes are currently made available only through
260
+ the GeoRuby library (http://georuby.rubyforge.org): This is where the
261
+ *Point.from_x_y* in the example above comes from. It is a goal
262
+ of a future release of the Spatial Adapter to support additional
263
+ geometric datatype libraries, such as Ruby/GEOS, as long as they
264
+ can support reading and writing of EWKB.
265
+
266
+
267
+
268
+ === Warning
269
+
270
+ - Since ActiveRecord seems to keep only the string values directly
271
+ returned from the database, it translates from these to the correct
272
+ types everytime an attribute is read, which is probably ok for simple
273
+ types, but might be less than efficient for geometries, since the EWKB
274
+ string has to be parsed everytime. Also it means you cannot modify the
275
+ geometry object returned from an attribute directly :
276
+
277
+ place = Place.first
278
+ place.the_geom.y=123456.7
279
+
280
+ - Since the translation to a geometry is performed everytime the_geom
281
+ is read, the change to y will not be saved! You would have to do
282
+ something like this :
283
+
284
+ place = Place.first
285
+ the_geom = place.the_geom
286
+ the_geom.y=123456.7
287
+ place.the_geom = the_geom
288
+
289
+
290
+ == License
291
+
292
+ Spatial Adapter for Rails is released under the MIT license.
293
+ Postgis Adapter is released under the MIT license.
294
+
295
+
296
+ == Support
297
+
298
+ Tested using rails 2.2.2 / postgresql 8.3.5 / postgis 1.3.3 / linux / osx
299
+
300
+ Any questions, enhancement proposals, bug notifications or corrections:
301
+
302
+
303
+ === PostgisAdapter
304
+
305
+ Project Tracker http://nofxx.lighthouseapp.com/projects/20712-postgis_adapter
306
+
307
+
308
+ === SpatialAdapter
309
+
310
+
311
+ guilhem.vellut+georuby@gmail.com.
data/Rakefile ADDED
@@ -0,0 +1,100 @@
1
+ #$:.unshift(File.join(File.dirname(__FILE__) ,'../../gems/georuby/lib/'))
2
+ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
3
+ require 'rake'
4
+ require 'spec/rake/spectask'
5
+ require 'rake/rdoctask'
6
+ require 'active_record'
7
+ require 'active_record/connection_adapters/postgresql_adapter'
8
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
9
+ require File.dirname(__FILE__) + '/lib/postgis_adapter'
10
+
11
+ # Generate all the Rake tasks
12
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)PostgisAdapter::VERSION
13
+ $hoe = Hoe.new('postgis_adapter', PostgisAdapter::VERSION) do |p|
14
+ p.developer('Marcos Piccinini', 'x@nofxx.com')
15
+ p.summary = "Postgis Adapter for Activer Record"
16
+ p.description = "Postgis Adapter for Activer Record"
17
+ p.url = "http://github.com/nofxx/postgis_adapter"
18
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
19
+ # p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
20
+ p.rubyforge_name = "postgis_adapter" # TODO this is default value
21
+ p.extra_deps = [
22
+ ['activerecord','>= 2.0.2'],
23
+ ]
24
+ p.extra_dev_deps = [
25
+ ['newgem', ">= #{::Newgem::VERSION}"]
26
+ ]
27
+
28
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
29
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
30
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
31
+ p.rsync_args = '-av --delete --ignore-errors'
32
+ end
33
+
34
+ require 'newgem/tasks' # load /tasks/*.rake
35
+ Dir['tasks/**/*.rake'].each { |t| load t }
36
+
37
+ # TODO - want other tests/tasks run by default? Add them to the list
38
+ # task :default => [:spec, :features]
39
+
40
+ desc 'Default: run specs.'
41
+ task :default => :spec
42
+
43
+ desc "Run all specs"
44
+ Spec::Rake::SpecTask.new do |t|
45
+ t.spec_files = FileList['spec/*_spec.rb']
46
+ t.spec_opts = ['--options', 'spec/spec.opts']
47
+ unless ENV['NO_RCOV']
48
+ t.rcov = true
49
+ t.rcov_dir = 'coverage'
50
+ t.rcov_opts = ['--html', '--exclude', "\.autotest,schema.rb,init.rb,\.gitignore,spec\/spec_helper.rb,spec\/db/*,#{ENV['GEM_HOME']}"]
51
+ end
52
+ end
53
+
54
+ desc "Look for TODO and FIXME tags in the code"
55
+ task :todo do
56
+ egrep /(FIXME|TODO|TBD)/
57
+ end
58
+
59
+ namespace :db do
60
+ task :migrate do
61
+ load('spec/db/schema_postgis.rb')
62
+ end
63
+ end
64
+
65
+ desc "Generate the documentation"
66
+ Rake::RDocTask::new do |rdoc|
67
+ rdoc.rdoc_dir = 'doc/'
68
+ rdoc.title = "PostGIS Adapter for Rails Documentation"
69
+ rdoc.options << '--line-numbers' << '--inline-source'
70
+ rdoc.rdoc_files.include('README.rdoc')
71
+ rdoc.rdoc_files.include('lib/**/*.rb')
72
+ end
73
+
74
+ # From Rspec Rakefile
75
+ #
76
+ def egrep(pattern)
77
+ Dir['**/*.rb'].each do |fn|
78
+ count = 0
79
+ open(fn) do |f|
80
+ while line = f.gets
81
+ count += 1
82
+ if line =~ pattern
83
+ puts "#{fn}:#{count}:#{line}"
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ desc "verify_committed, verify_rcov, post_news, release"
91
+ task :complete_release => [:verify_committed, :post_news, :release]
92
+
93
+ desc "Verifies that there is no uncommitted code"
94
+ task :verify_committed do
95
+ IO.popen('git status') do |io|
96
+ io.each_line do |line|
97
+ raise "\n!!! Do a git commit first !!!\n\n" if line =~ /^#\s*modified:/
98
+ end
99
+ end
100
+ end