activerecord-postgis-adapter 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/Documentation.rdoc +322 -0
  2. data/History.rdoc +5 -0
  3. data/README.rdoc +42 -290
  4. data/Version +1 -1
  5. data/lib/active_record/connection_adapters/postgis_adapter.rb +35 -21
  6. data/lib/active_record/connection_adapters/postgis_adapter/rails3/create_connection.rb +96 -0
  7. data/lib/active_record/connection_adapters/postgis_adapter/{databases.rake → rails3/databases.rake} +7 -1
  8. data/lib/active_record/connection_adapters/postgis_adapter/{main_adapter.rb → rails3/main_adapter.rb} +9 -9
  9. data/lib/active_record/connection_adapters/postgis_adapter/{spatial_column.rb → rails3/spatial_column.rb} +4 -8
  10. data/lib/active_record/connection_adapters/postgis_adapter/{spatial_table_definition.rb → rails3/spatial_table_definition.rb} +5 -9
  11. data/lib/active_record/connection_adapters/postgis_adapter/rails4/create_connection.rb +88 -0
  12. data/lib/active_record/connection_adapters/postgis_adapter/rails4/databases.rake +52 -0
  13. data/lib/active_record/connection_adapters/postgis_adapter/rails4/main_adapter.rb +310 -0
  14. data/lib/active_record/connection_adapters/postgis_adapter/rails4/postgis_database_tasks.rb +232 -0
  15. data/lib/active_record/connection_adapters/postgis_adapter/rails4/spatial_column.rb +220 -0
  16. data/lib/active_record/connection_adapters/postgis_adapter/rails4/spatial_table_definition.rb +140 -0
  17. data/lib/active_record/connection_adapters/postgis_adapter/railtie.rb +3 -28
  18. data/lib/active_record/connection_adapters/postgis_adapter/{arel_tosql.rb → shared/arel_tosql.rb} +3 -7
  19. data/lib/active_record/connection_adapters/postgis_adapter/shared/jdbc_compat.rb +133 -0
  20. data/lib/active_record/connection_adapters/postgis_adapter/shared/railtie.rb +66 -0
  21. data/lib/active_record/connection_adapters/postgis_adapter/shared/setup.rb +57 -0
  22. data/lib/active_record/connection_adapters/postgis_adapter/{version.rb → shared/version.rb} +1 -1
  23. data/lib/activerecord-postgis-adapter.rb +37 -0
  24. data/lib/rgeo/active_record/postgis_adapter/railtie.rb +1 -1
  25. data/test/tc_basic.rb +43 -16
  26. data/test/tc_ddl.rb +2 -2
  27. data/test/tc_nested_class.rb +2 -2
  28. data/test/tc_spatial_queries.rb +14 -9
  29. data/test/tc_tasks.rb +110 -0
  30. metadata +27 -14
  31. data/lib/active_record/connection_adapters/postgis_adapter/jdbc_connection.rb +0 -78
  32. data/lib/active_record/connection_adapters/postgis_adapter/pg_connection.rb +0 -27
@@ -0,0 +1,322 @@
1
+ == \Documentation for the PostGIS \ActiveRecord Adapter
2
+
3
+ This document provides basic how-to information that should help get you started with integrating your Rails application with a PostGIS database. We cover three parts:
4
+
5
+ * How to install the adapter, and how to configure your database.yml.
6
+ * How to set up and configure spatial columns and tables.
7
+ * How to read, write, and query spatial data.
8
+
9
+ This document is part of the distribution for the activerecord-postgis-adapter gem. For more information, please visit http://dazuma.github.com/activerecord-postgis-adapter.
10
+
11
+ == Installation and Configuration
12
+
13
+ === General Installation Considerations
14
+
15
+ Generally, we recommend starting with the latest versions of Ruby, Rails, PostgreSQL, and PostGIS. As of this writing, those are Ruby 1.9.3, Rails 3.2, PostgreSQL 9.2, and PostGIS 2.0. If you cannot upgrade, the minimum supported configuration is the following:
16
+
17
+ * Ruby 1.8.7
18
+ * Rails 3.0.3
19
+ * PostgreSQL 9.0
20
+ * PostGIS 1.5
21
+
22
+ However, older software versions can make for a more involved setup process, so we recommend using the latest available if possible.
23
+
24
+ As of this writing, Rails 4.0.0 beta 1 has just been released. This version of activerecord-postgis-adapter does support Rails 4, but because the software is still beta, the usual caveats apply.
25
+
26
+ JRuby and the JDBC Postgres Adapter is supported. (But, as of this writing, the JDBC adapters themselves are not yet compatible with Rails 4.)
27
+
28
+ === Creating a Spatial Rails App
29
+
30
+ This section covers starting a new Rails application from scratch. If you need to add geospatial capabilities to an existing Rails application (i.e. you need to convert a non-spatial database to a spatial database), see the section on "Upgrading a Database With Spatial Features" below.
31
+
32
+ To create a new Rails application using activerecord-postgis-adapter, start by using the postgresql adapter.
33
+
34
+ rails new my_app --database=postgresql
35
+
36
+ Next, add the activerecord-postgis-adapter gem to the Gemfile as follows:
37
+
38
+ gem 'activerecord-postgis-adapter'
39
+
40
+ We also recommend including the "squeel" gem, which comes in very useful for writing spatial queries. Then run <code>bundle install</code> to complete your bundle.
41
+
42
+ The adapter includes a railtie that provides specialized rake tasks for managing spatial databases. Earlier versions of this adapter required you to load that railtie explicitly by adding a certain require statement to your <code>config/application.rb</code>. As of version 0.6, that explicit require statement is no longer necessary. If your code already has that require statement, it will not harm anything in this version, but it is considered deprecated.
43
+
44
+ Next, you need to modify your <code>config/database.yml</code> file to invoke the postgis adapter, and to provide additional information it may need to set up a new database with spatial features. For example, at minimum, you will need to change the <code>adapter</code> field from "postgresql" to "postgis". Please see the Configuration sections below to see how to set up your database configs properly before proceeding.
45
+
46
+ Once you have set up your database configs, you should be able to run:
47
+
48
+ rake db:create
49
+
50
+ to create your development database. The adapter will automatically add the PostGIS spatial definitions to your database.
51
+
52
+ When you create your production database, you'll also need to add PostGIS to that database. The adapter does not provide rake tasks for setting up your production database; you will have to do that yourself. Generally, that means logging into your newly created production database and running, as a superuser:
53
+
54
+ CREATE EXTENSION postgis;
55
+
56
+ For more information, see the PostGIS documentation, or any relevant documentation provided by your hosting service.
57
+
58
+ === Upgrading an Existing Database With Spatial Features
59
+
60
+ If you have an existing Rails app and an existing database that uses Postgres, and you want to add geospatial features, you should follow these steps.
61
+
62
+ First, add the activerecord-postgis-adapter gem to the Gemfile, and update your bundle by running <code>bundle install</code>.
63
+
64
+ Next, modify your <code>config/database.yml</code> file to invoke the postgis adapter, as described above. At minimum, you will need to change the <code>adapter</code> field from "postgresql" to "postgis".
65
+
66
+ Once you have set up your database configs, run:
67
+
68
+ rake db:gis:setup
69
+
70
+ This rake task adds the PostGIS extension to your existing development database.
71
+
72
+ Prior to deployment, you will also need to add the PostGIS extension to your production database. Generally, that means logging into your production database and running, as a superuser:
73
+
74
+ CREATE EXTENSION postgis;
75
+
76
+ For more information, see the PostGIS documentation, or any relevant documentation provided by your hosting service.
77
+
78
+ === Recommended Configuration
79
+
80
+ Setting up the database.yml is a bit of an art. In this section, we'll cover a recommended configuration to get you started. This should be sufficient for most cases. We'll cover some of the alternate configuration options in more detail in the next section.
81
+
82
+ Assuming you have at least PostgreSQL 9.2 and PostGIS 2.0, the following is the recommended configuration:
83
+
84
+ development:
85
+ adapter: postgis
86
+ encoding: unicode
87
+ postgis_extension: true
88
+ schema_search_path: public,postgis
89
+ pool: 5
90
+ database: my_app_development # substitute your dev database name
91
+ username: my_app_user # substitute the username your app will use to connect
92
+ password: my_app_password # substitute the user's password
93
+ su_username: my_global_user # substitute a superuser for the database
94
+ su_password: my_global_pasword # substitute the superuser's password
95
+
96
+ The adapter name _must_ be set to "postgis" to invoke the adapter.
97
+
98
+ The <code>postgis_extension</code> tells the adapter to add the PostGIS extension to the database when the database is created (i.e. <code>rake db:create</code>). If it is missing, you will need to add PostGIS to your database through some other mechanism.
99
+
100
+ The <code>schema_search_path</code> is an important value. If you include a schema called "postgis" in the search path, the adapter will isolate all the PostGIS-specific definitions, including data types, functions, views, and so forth, into that schema instead of including them in the default "public" schema. Then, when Rails needs to dump the schema (for example, to replicate it for the test database), it can use that isolation to omit the PostGIS definitions from cluttering the schema dump.
101
+
102
+ The credentials that your app will use to connect to the database should be given in the <code>username</code> and <code>password</code> fields. Generally, for security reasons, it is not a good idea for this user to have "superuser" privileges. However, the adapter _does_ need superuser privileges for one function: installing PostGIS into the database when the database is first created. Therefore, you should provide a _second_ set of credentials, <code>su_username</code> and <code>su_password</code>, which identify a superuser account. This account will be used once, when you create the database (i.e. rake db:create), and not afterward.
103
+
104
+ === Alternate Configuration Schemes
105
+
106
+ Here are some configuration options for other cases.
107
+
108
+ *If you have an older PostgreSQL or an older PostGIS* you will not be able to use the Postgres extension mechanism to install PostGIS into your database. In this case, instead of including <code>postgis_extension</code>, you should include <code>script_dir</code> in the configuration. This should be set to a directory containing two files that contain all the PostGIS-provided spatial definitions: <code>postgis.sql</code> and <code>spatial_ref_sys.sql</code>.
109
+
110
+ This directory is usually in the share/contrib directory of your PostgreSQL installation. To find it, run
111
+
112
+ pg_config --sharedir
113
+
114
+ Then, append <code>contrib</code>, and look for a subdirectory named "postgis-(version)". For example, if you installed PostgreSQL in /usr/local, and you are running PostGIS 1.5, you should probably set <code>script_dir</code> to <code>/usr/local/share/contrib/postgis-1.5</code>.
115
+
116
+ *If you are using a template to install PostGIS into your database* then set the <code>template</code> configuration as appropriate, and _omit_ both the <code>postgis_extension</code> and <code>script_dir</code> configurations. In this case, you also do not need to include <code>su_username</code> or <code>su_password</code>, since those configurations apply only to adding the extension or using the script dir.
117
+
118
+ *If you do not want the spatial declarations to live in a separate schema* then do _not_ include "postgis" on the <code>schema_search_path</code>. Note that we recommend separating PostGIS into a separate schema, because that is the best way to ensure <code>rake test</code> works properly and is able to create the test database.
119
+
120
+ == Spatial Database Structure
121
+
122
+ A spatial database is one that includes a set of data types, functions, tables, and other objects related to geospatial data. When these objects are present in your database, you can use them to store and query spatial objects such as points, lines, and polygons.
123
+
124
+ PostGIS is a plugin for PostgreSQL that provides definitions for the objects you need to add to a database to enable geospatial capabilities.
125
+
126
+ When you create your Rails database as described above in the section on installation and configuration, activerecord-postgis-adapter automatically invokes PostGIS to add the appropriate definitions to your database. You can determine whether your database includes the correct definitions by attempting to invoke the POSTGIS_VERSION function:
127
+
128
+ SELECT POSTGIS_VERSION(); # succeeds if PostGIS objects are present.
129
+
130
+ Standard spatial databases also include a table called <code>spatial_ref_sys</code>. This table includes a set of "spatial reference systems", or coordinate systems--- for example, WGS84 latitude and longitude, or Mercator Projection. Spatial databases also usually include a table called <code>geometry_columns</code>, which includes information on each database column that includes geometric data. In recent versions of PostGIS, <code>geometry_columns</code> is actually not a table but a view into the system catalogs.
131
+
132
+ === Creating Spatial Tables
133
+
134
+ To store spatial data, you must create a column with a spatial type. PostGIS provides a variety of spatial types, including point, linestring, polygon, and different kinds of collections. These types are defined in a standard produced by the Open Geospatial Consortium. Furthermore, you can specify options indicating the coordinate system and number of coordinates for the values you are storing.
135
+
136
+ The activerecord-postgis-adapter extends \ActiveRecord's migration syntax to support these spatial types. The following example creates four spatial columns in a table:
137
+
138
+ create_table :my_spatial_table do |t|
139
+ t.column :shape1, :geometry
140
+ t.geometry :shape2
141
+ t.line_string :path, :srid => 3785
142
+ t.point :lonlat, :geographic => true
143
+ t.point :lonlatheight, :geographic => true, :has_z => true
144
+ end
145
+
146
+ The first column, "shape1", is created with type "geometry". This is a general "base class" for spatial types; the column declares that it can contain values of _any_ spatial type. The second column, "shape2", uses a shorthand syntax for the same type. Like "normal" types, you can create a column either by invoking <code>column</code> or invoking the name of the type directly.
147
+
148
+ The third column, "path", has a specific geometric type, <code>line_string</code>. It also specifies an SRID (spatial reference ID) that indicates which coordinate system it expects the data to be in. The column now has a "constraint" on it; it will accept only LineString data, and only data whose SRID is 3785.
149
+
150
+ The fourth column, "lonlat", has the <code>point</code> type, and accepts only Point data. Furthermore, it declares the column as "geographic", which means it accepts longitude/latitude data, and performs calculations such as distances using a spheroidal domain.
151
+
152
+ The fifth column, "lonlatheight", is a geographic (longitude/latitude) point that also includes a third "z" coordinate that can be used to store height information.
153
+
154
+ The following are the data types understood by PostGIS and exposed by activerecord-postgis-adapter:
155
+
156
+ * <tt>:geometry</tt> -- Any geometric type
157
+ * <tt>:point</tt> -- Point data
158
+ * <tt>:line_string</tt> -- LineString data
159
+ * <tt>:polygon</tt> -- Polygon data
160
+ * <tt>:geometry_collection</tt> -- Any collection type
161
+ * <tt>:multi_point</tt> -- A collection of Points
162
+ * <tt>:multi_line_string</tt> -- A collection of LineStrings
163
+ * <tt>:multi_polygon</tt> -- A collection of Polygons
164
+
165
+ Following are the options understood by the adapter:
166
+
167
+ * <tt>:geographic</tt> -- If set to true, create a PostGIS geography column for longitude/latitude data over a spheroidal domain; otherwise create a geometry column in a flat coordinate system. Default is false. Also implies :srid set to 4326.
168
+ * <tt>:srid</tt> -- Set a SRID constraint for the column. Default is 4326 for a geography column, or -1 for a geometry column. Note that PostGIS currently (as of version 2.0) requires geography columns to have SRID 4326, so this constraint is of limited use for geography columns.
169
+ * <tt>:has_z</tt> -- Specify that objects in this column include a Z coordinate. Default is false.
170
+ * <tt>:has_m</tt> -- Specify that objects in this column include an M coordinate. Default is false.
171
+
172
+ The adapter also extends the \ActiveRecord migration syntax for creating spatial indexes. To create a PostGIS spatial index, simply set the :spatial option to true, as follows:
173
+
174
+ change_table :my_spatial_table do |t|
175
+ t.index :lonlat, :spatial => true
176
+ end
177
+
178
+ === Configuring the \ActiveRecord class
179
+
180
+ \ActiveRecord's usefulness stems from the way it automatically configures classes based on the database structure and schema. If a column in the database has an integer type, \ActiveRecord automatically casts the data to a Ruby Integer. In the same way, the activerecord-postgis-adapter automatically casts spatial data to a corresponding RGeo data type.
181
+
182
+ However, RGeo offers more "flexibility" in its type system than can be interpreted solely from analyzing the database column. For example, you can configure RGeo objects to exhibit certain behaviors related to their serialization, validation, coordinate system, or computation. These settings are embodied in the RGeo "factory" associated with the object.
183
+
184
+ Therefore, you can configure the adapter to use a particular factory (i.e. a particular combination of settings) for data associated with each column in the database. This is done by calling class methods on the \ActiveRecord class associated with that database table. Specifically, you can call <code>set_rgeo_factory_for_column</code> to set the factory that \ActiveRecord uses for a particular column.
185
+
186
+ You can also provide a "factory generator" function which takes information from the database column and returns a suitable factory. Set the factory generator by setting the <code>rgeo_factory_generator</code> class attribute of your \ActiveRecord class. The generator should be a callable object that takes a hash that could include the following keys:
187
+
188
+ * <tt>:srid</tt> -- the SRID of the database column
189
+ * <tt>:has_z_coordinate</tt> -- true if the database column has a Z coordinate
190
+ * <tt>:has_m_coordinate</tt> -- true if the database column has a M coordinate
191
+ * <tt>:geographic</tt> -- true if the database column is geographic instead of geometric
192
+
193
+ Here are some examples, given the spatial table defined above:
194
+
195
+ class MySpatialTable < ActiveRecord::Base
196
+
197
+ # By default, use the GEOS implementation for spatial columns.
198
+ self.rgeo_factory_generator = RGeo::Geos.factory_generator
199
+
200
+ # But use a geographic implementation for the :lonlat column.
201
+ set_rgeo_factory_for_column(:lonlat, RGeo::Geographic.spherical_factory(:srid => 4326))
202
+
203
+ end
204
+
205
+ The <code>rgeo_factory_generator</code> attribute and <code>set_rgeo_factory_for_column</code> method are actually implemented (and documented) in the "rgeo-activerecord" gem, which is a dependency of the activerecord-postgis-adapter.
206
+
207
+ === Schema Dump and Reload
208
+
209
+ The presence of geospatial data in a database causes some issues with \ActiveRecord's schema dump and restore functions. This is because (1) installing PostGIS into your database injects a lot of objects in your database that can clutter up schema dumps, and (2) to define a spatial column correctly, you generally must call a SQL function such as AddGeometryColumn(), and Rails's schema dumper isn't smart enough to reproduce those function calls.
210
+
211
+ Because of this, we recommend the following.
212
+
213
+ * Install the PostGIS definitions in a separate schema called "postgis" (as described in the recommended installation procedure above). The activerecord-postgis-adapter will ignore a schema called "postgis" when dumping the schema, thus omitting the clutter.
214
+
215
+ * Set the \ActiveRecord schema format to <code>:ruby</code>, _not_ <code>:sql</code>. The former emits higher level commands that can be interpreted correctly to reproduce the schema. The latter, however, emits low level SQL, which loses information such as the fact that AddGeometryColumn() was originally used to generate a column. Executing a <code>:sql</code> format schema dump will _not_ correctly reproduce the schema.
216
+
217
+ Of course, the above discussion is really relevant only if you are using the \ActiveRecord rake tasks that create and restore databases, either directly such as <code>rake db:create</code> or indirectly such as <code>rake test</code>. It does not have any effect on running migrations or normal website execution.
218
+
219
+ == Working With Spatial Data
220
+
221
+ Of course, you're using this adapter because you want to work with geospatial data in your \ActiveRecord models. Once you've installed the adapter, set up your database, and run your migrations, you can interact directly with spatial data in your models as RGeo objects.
222
+
223
+ RGeo is a Ruby implementation of the industry standard OGC Simple Features specification. It's a set of data types that can represent a variety of geospatial objects such as points, lines, polygons, and collections. It also provides the standard set of spatial analysis operations such as computing intersections or bounding boxes, calculating length or area, and so forth. We recommend browsing the RGeo documentation for a clearer understanding of its capabilities. For now, just note that the data values you will be working with are all RGeo geometry objects.
224
+
225
+ === Reading and Writing Spatial Columns
226
+
227
+ When you access a spatial attribute on your \ActiveRecord model, it is given to you as an RGeo geometry object (or nil, for attributes that allow null values). You can then call the RGeo api on the object. For example, consider the MySpatialTable class we worked with above:
228
+
229
+ record = MySpatialTable.find(1)
230
+ p = record.lonlat # Returns an RGeo::Feature::Point
231
+ puts p.x # displays the x coordinate
232
+ puts p.geometry_type.type_name # displays "Point"
233
+
234
+ The RGeo factory for the value is determined by how you configured the \ActiveRecord class, as described above. In this case, we explicitly set a spherical factory for the <code>:lonlat</code> column:
235
+
236
+ factory = p.factory # returns a spherical factory
237
+
238
+ You can set a spatial attribute by providing an RGeo geometry object, or by providing the WKT string representation of the geometry. If a string is provided, the activerecord-postgis-adapter will attempt to parse it as WKT and set the value accordingly.
239
+
240
+ record.lonlat = 'POINT(-122, 47)' # sets the value to the given point
241
+
242
+ If the WKT parsing fails, the value currently will be silently set to nil. In the future, however, this will raise an exception.
243
+
244
+ record.lonlat = 'POINT(x)' # sets the value to nil
245
+
246
+ If you set the value to an RGeo object, the factory needs to match the factory for the attribute. If the factories do not match, activerecord-postgis-adapter will attempt to cast the value to the correct factory.
247
+
248
+ p2 = factory.point(-122, 47) # p2 is a point in a spherical factory
249
+ record.lonlat = p2 # sets the value to the given point
250
+ record.shape1 = p2 # shape1 uses a flat geos factory, so it
251
+ # will cast p2 into that coordinate system
252
+ # before setting the value
253
+ record.save
254
+
255
+ If, however, you attempt to set the value to the wrong type-- for example, setting a linestring attribute to a point value, you will get an exception from Postgres when you attempt to save the record.
256
+
257
+ record.path = p2 # This will appear to work, but...
258
+ record.save # This will raise an exception from the database
259
+
260
+ === Spatial Queries
261
+
262
+ You can create simple queries based on representational equality in the same way you would on a scalar column:
263
+
264
+ record2 = MySpatialTable.where(:lonlat => factory.point(-122, 47)).first
265
+
266
+ You can also use WKT:
267
+
268
+ record3 = MySpatialTable.where(:lonlat => 'POINT(-122 47)').first
269
+
270
+ Note that these queries use representational equality, meaning they return records where the lonlat value matches the given value exactly. A 0.00001 degree difference would not match, nor would a different representation of the same geometry (like a multipoint with a single element). Equality queries aren't generally all that useful in real world applications. Typically, if you want to perform a spatial query, you'll look for, say, all the points within a given area. For those queries, you'll need to use the standard spatial SQL functions provided by PostGIS.
271
+
272
+ Unfortunately, Rails by itself doesn't provide good support for embedding arbitrary function calls in your where clause. You could get around this by writing raw SQL. But the solution we recommend is to use the "squeel" gem. This gem extends the \ActiveRecord syntax to support more complex queries.
273
+
274
+ Let's say you wanted to find all records whose lonlat fell within a particular polygon. In the query, you can accomplish this by calling the ST_Intersects() SQL function on the lonlat and the polygon. That is, you'd want to generate SQL that looks something like this:
275
+
276
+ SELECT * FROM my_spatial_table WHERE ST_Intersects(lonlat, <i>my-polygon</i>);
277
+
278
+ Using squeel, you can write this as follows:
279
+
280
+ my_polygon = get_my_polygon() # Obtain the polygon as an RGeo geometry
281
+ MySpatialTable.where{st_intersects(lonlat, my_polygon)}.first
282
+
283
+ Notice the curly brackets instead of parentheses in the where clause. This is how to write squeel queries: squeel is actually a DSL, and you're passing a block to the where method instead of an argument list. Also note that Squeel requires \ActiveRecord 3.1 or later to handle SQL function calls such as ST_Intersects.
284
+
285
+ As another example, one common query is to find all objects displaying in a window. This can be done using the overlap (&&) operator with a bounding box. Here's an example that finds linestrings in the "path" column that intersect a bounding box:
286
+
287
+ sw = get_sw_corner_in_projected_coordinates()
288
+ ne = get_ne_corner_in_projected_coordinates()
289
+ window = RGeo::Cartesian::BoundingBox.create_from_points(sw, ne)
290
+ MySpatialTable.where{path.op('&&', window)}.all
291
+
292
+ Note that bounding box queries make sense only in a projected coordinate system; you shouldn't try to run such a query against a lat/long (geographic) column.
293
+
294
+ == License
295
+
296
+ Copyright 2010-2013 Daniel Azuma
297
+
298
+ All rights reserved.
299
+
300
+ Redistribution and use in source and binary forms, with or without
301
+ modification, are permitted provided that the following conditions are met:
302
+
303
+ * Redistributions of source code must retain the above copyright notice,
304
+ this list of conditions and the following disclaimer.
305
+ * Redistributions in binary form must reproduce the above copyright notice,
306
+ this list of conditions and the following disclaimer in the documentation
307
+ and/or other materials provided with the distribution.
308
+ * Neither the name of the copyright holder, nor the names of any other
309
+ contributors to this software, may be used to endorse or promote products
310
+ derived from this software without specific prior written permission.
311
+
312
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
313
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
314
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
315
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
316
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
317
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
318
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
319
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
320
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
321
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
322
+ POSSIBILITY OF SUCH DAMAGE.
data/History.rdoc CHANGED
@@ -1,3 +1,8 @@
1
+ === 0.6.0 / 2013-02-28
2
+
3
+ * Experimental support for the recently released Rails 4.0 beta.
4
+ * Documentation improvements.
5
+
1
6
  === 0.5.1 / 2013-02-04
2
7
 
3
8
  * Database creation properly treats geometry_columns as a view when setting owner. (Pull request by hendrikstier)
data/README.rdoc CHANGED
@@ -1,300 +1,52 @@
1
1
  == PostGIS \ActiveRecord Adapter
2
2
 
3
- The PostGIS \ActiveRecord Adapter is an \ActiveRecord connection adapter
4
- based on the standard postgresql adapter. It extends the standard adapter
5
- to provide support for the spatial extensions provided by PostGIS, using
6
- the {RGeo}[http://github.com/dazuma/rgeo] library to represent spatial
7
- data in Ruby. Like the standard postgresql adapter, this adapter requires
8
- the pg gem.
9
-
10
- == What This Adapter Provides
11
-
12
- === Spatial Migrations
13
-
14
- First, this adapter extends the migration syntax to support creating
15
- spatial columns and indexes. To create a spatial column, use the
16
- <tt>:geometry</tt> type, or any of the OGC spatial types such as
17
- <tt>:point</tt> or <tt>:line_string</tt> to set a geometry type
18
- constraint. You may also provide any of the following options:
19
-
20
- * <tt>:geographic</tt> -- If set to true, create a PostGIS geography
21
- column; otherwise create a geometry column. Default is false.
22
- * <tt>:srid</tt> -- Set a SRID constraint for the column. Default is 4326
23
- for a geography column, or -1 for a geometry column. Note that PostGIS
24
- currently (as of version 1.5.2) requires geography columns to have SRID
25
- 4326, so this constraint is of limited use for geography columns.
26
- * <tt>:has_z</tt> -- Specify that objects in this column include a Z
27
- coordinate. Default is false.
28
- * <tt>:has_m</tt> -- Specify that objects in this column include an M
29
- coordinate. Default is false.
30
-
31
- To create a spatial index, set the <tt>:spatial</tt> option to true when
32
- creating the index.
33
-
34
- Examples:
35
-
36
- create_table :my_spatial_table do |t|
37
- t.column :shape, :geometry # or t.geometry :shape
38
- t.line_string :path, :srid => 3785
39
- t.point :lonlat, :geographic => true
40
- end
41
- change_table :my_spatial_table do |t|
42
- t.index :lonlat, :spatial => true
43
- end
44
-
45
- === Spatial Attributes
46
-
47
- When this adapter is in use, spatial attributes in your \ActiveRecord
48
- objects will have RGeo geometry values. You can set spatial attributes
49
- either to RGeo geometry objects, or to strings in WKT (well-known text)
50
- format, which the adapter will automatically convert to geometry objects.
51
-
52
- Spatial objects in RGeo are tied to a factory that specifies the
53
- coordinate system as well as other behaviors of the object. You must
54
- therefore specify a factory for each spatial column (attribute) in your
55
- \ActiveRecord class. You can either set an explicit factory for a specific
56
- column, or provide a factory generator that will yield the appropriate
57
- factory for the table's spatial columns based on their types. For the
58
- former, call the <tt>set_rgeo_factory_for_column</tt> class method on your
59
- \ActiveRecord class. For the latter, set the rgeo_factory_generator class
60
- attribute. This generator should understand the usual <tt>:srid</tt>,
61
- <tt>:has_z_coordinate</tt>, and <tt>:has_m_coordinate</tt> options. It
62
- will also be passed a <tt>:geographic</tt> option indicating whether the
63
- column is a geography column. The set_rgeo_factory_for_column and
64
- rgeo_factory_generator methods are actually implemented and documented in
65
- the "rgeo-activerecord" gem.
66
-
67
- Examples, given the spatial table defined above:
68
-
69
- class MySpatialTable < ActiveRecord::Base
70
-
71
- # By default, use the GEOS implementation for spatial columns.
72
- self.rgeo_factory_generator = RGeo::Geos.factory_generator
73
-
74
- # But use a geographic implementation for the :lonlat column.
75
- set_rgeo_factory_for_column(:lonlat, RGeo::Geographic.spherical_factory(:srid => 4326))
76
-
77
- end
78
-
79
- Now you can interact with the data using the RGeo types:
80
-
81
- rec = MySpatialTable.new
82
- rec.lonlat = 'POINT(-122 47)' # You can set by feature object or WKT.
83
- loc = rec.lonlat # Accessing always returns a feature object, in
84
- # this case, a geographic that understands latitude.
85
- loc.latitude # => 47
86
- rec.shape = loc # the factory for the :shape column is GEOS, so the
87
- # value will be cast from geographic to GEOS.
88
- RGeo::Geos.is_geos?(rec.shape) # => true
89
-
90
- === Spatial Queries
91
-
92
- You can create simple queries based on objective equality in the same way
93
- you would on a scalar column:
94
-
95
- rec = MySpatialTable.where(:lonlat => RGeo::Geos.factory.point(-122, 47)).first
96
-
97
- You can also use WKT:
98
-
99
- rec = MySpatialTable.where(:lonlat => 'POINT(-122 47)').first
100
-
101
- Most more complex spatial queries require the use of SQL functions. You
102
- can write such queries in raw SQL, but you may find the "squeel" gem
103
- very helpful in this regard. Using squeel, you can write queries like
104
- the following:
105
-
106
- my_polygon = get_my_polygon()
107
- MySpatialTable.where{st_intersects(lonlat, my_polygon)}.first
108
-
109
- Note that using squeel to create SQL functions requires Rails 3.1 or later.
110
-
111
- One common query is to find all objects displaying in a window. This can
112
- be done using the overlap (&&) operator with a bounding box. Here's an
113
- example that finds linestrings in the "path" column that intersect a
114
- bounding box:
115
-
116
- sw = get_sw_corner_in_projected_coordinates()
117
- ne = get_ne_corner_in_projected_coordinates()
118
- window = RGeo::Cartesian::BoundingBox.create_from_points(sw, ne)
119
- MySpatialTable.where{path.op('&&', window)}.all
120
-
121
- Note that bounding box queries make sense only in a projected coordinate
122
- system; you shouldn't try to run such a query against a lat/long
123
- (geographic) column.
124
-
125
- == Installation And Configuration
126
-
127
- === Installing The Adapter Gem
128
-
129
- This adapter has the following requirements:
3
+ The activerecord-postgis-adapter is a plugin that provides access to features of the PostGIS geospatial database from \ActiveRecord. Technically, it extends the standard postgresql adapter to provide support for the spatial data types and features added by the PostGIS extension. It uses the {RGeo}[http://github.com/dazuma/rgeo] library to represent spatial data in Ruby.
130
4
 
131
- * Ruby 1.8.7 or later. Ruby 1.9.2 or later preferred. JRuby 1.6.3 or
132
- later also supported.
5
+ == About the PostGIS Adapter
6
+
7
+ This is a brief summary covering how to use activerecord-postgis-adapter. For full documentation, see Documentation.rdoc.
8
+
9
+ === Features
10
+
11
+ The adapter provides three basic capabilities.
12
+
13
+ First, it provides *spatial migrations*. It extends the \ActiveRecord migration syntax to support creating spatially-typed columns and spatial indexes. You can control the various PostGIS-provided attributes such as srid, dimension, and geographic vs geometric math.
14
+
15
+ Second, it recognizes spatial types and casts them properly to RGeo geometry objects. The adapter can configure these objects automatically based on the srid and dimension in the database table, or you can tell it to convert the data to a different form. You can also set attribute data using WKT format.
16
+
17
+ Third, it lets you include simple spatial data in queries. WKT format data and RGeo objects can be embedded in where clauses. If you include the Squeel gem, the adapter also supports advanced queries utilizing the standard SQL spatial function set.
18
+
19
+ === Requirements
20
+
21
+ The adapter has the following requirements.
22
+
23
+ * Ruby 1.8.7 or later. Ruby 1.9.2 or later preferred. JRuby 1.6.3 or later also supported.
133
24
  * PostgreSQL 9.0 or later.
134
25
  * PostGIS 1.5, PostGIS 2.0, or later.
135
- * \ActiveRecord 3.0.3 or later. Earlier versions will not work.
136
- Should be compatible with Rails versions through 3.2.x.
137
- * rgeo gem 0.3.20 or later.
138
- * rgeo-activerecord gem 0.4.6 or later.
26
+ * \ActiveRecord 3.0.3 or later. Earlier versions will not work. Rails 4.0 is supported on an experimental basis.
27
+ * The rgeo and rgeo-activerecord gems are also required.
28
+
29
+ As of this writing, the JDBC Postgres driver is not yet compatible with Rails 4, so the combination of JRuby/JDBC/Rails 4 is not yet supported. Similarly, Rubinius receives limited testing and support.
30
+
31
+ === Installation and Configuration
32
+
33
+ To install this adapter in a Rails application, add it to your Gemfile:
139
34
 
140
- Please note that this version of the adapter is targeted towards Rails
141
- 3.x only. The upcoming version 0.6 will target Rails 4.0.
35
+ gem 'activerecord-postgis-adapter'
142
36
 
143
- Install this adapter as a gem:
37
+ and run bundle install to update your bundle.
38
+
39
+ Alternately, if you are not using bundler, install it separately as a gem:
144
40
 
145
41
  gem install activerecord-postgis-adapter
146
42
 
147
- See the README for the "rgeo" gem, a required dependency, for further
148
- installation information.
149
-
150
- === Basic Setup
151
-
152
- To use this adapter, add this gem, "activerecord-postgis-adapter", to
153
- your Gemfile, and then request the adapter name "postgis" in your
154
- database connection configuration (which, for a Rails application, is in
155
- the config/database.yml file). Most of the rest of the configuration
156
- parameters are identical to those used by the stock "postgresql" adapter,
157
- so you can create a new Rails application using:
158
-
159
- rails new my_app --database=postgresql
160
-
161
- ...and then just change the adapter name to "postgis".
162
-
163
- Next, the PostGIS adapter includes a special railtie that provides
164
- support for PostGIS databases in ActiveRecord's rake tasks. This railtie
165
- is required in order to run, e.g., rake test. To install this railtie,
166
- you should add this line to your config/application.rb:
167
-
168
- require 'active_record/connection_adapters/postgis_adapter/railtie'
169
-
170
- Note that this railtie must load after the ActiveRecord railtie. That is,
171
- the above require command should appear after <tt>require 'rails/all'</tt>.
172
-
173
- Besides the adapter name "postgis", most of the other database connection
174
- configuration parameters are the same as for the stock postgresql adapter.
175
- However, there are several important differences:
176
-
177
- The <i>postgis_extension</i> parameter is specific to the PostGIS adapter,
178
- and directs the adapter to use PostgreSQL's CREATE EXTENSION mechanism to
179
- install the PostGIS types, functions, and tables to a newly created
180
- database. Generally, the value should be set to true, although you can
181
- also set it to a comma-delimited list of extension names (which should
182
- include the base "postgis" extension) if you want to customize which
183
- extensions are installed. This is the easiest and cleanest way to create
184
- a PostGIS-enabled database, but it requires PostgreSQL 9.1 or later AND
185
- PostGIS 2.0 or later.
186
-
187
- The <i>script_dir</i> parameter is specific to the PostGIS adapter, and
188
- provides an alternative mechanism for installing the PostGIS definitions
189
- into a new database if either PostgreSQL 9.1 or PostGIS 2.0 is not
190
- available. Its value should be set to the path to the directory containing
191
- the SQL scripts for PostGIS installation. This is the directory containing
192
- the files <tt>postgis.sql</tt> and <tt>spatial_ref_sys.sql</tt>. (A common
193
- setting might be <tt>/usr/local/share/contrib/postgis-1.5</tt>.)
194
-
195
- If you do not provide <i>postgis_extension</i> or <i>script_dir</i>, you
196
- will need to add the PostGIS definitions to the database manually.
197
- Generally, therefore, one of them is required at least for the test
198
- database, which is usually automatically created by the rake tasks.
199
-
200
- The <i>su_username</i> and <i>su_password</i> parameters are provided as
201
- optional parameters. If present, they specify an auxiliary PostgreSQL role
202
- that must have superuser privileges, and will be used for two functions:
203
-
204
- * Creation of the database. This is so the main database user that you
205
- specify doesn't need superuser or createdb privileges.
206
- * Installation of the PostGIS definitions, if requested by the presence
207
- of <i>script_dir</i>. This process normally requires a PostgreSQL role
208
- with superuser privileges, so again if you don't want your main database
209
- user to have superuser, you can perform this one-time procedure using
210
- this alternate user.
211
-
212
- Any schemas listed in the <i>schema_search_path</i> parameter are
213
- automatically created by <tt>rake db:create</tt>. This is arguably what
214
- the stock PostgreSQL adapter should be doing anyway.
215
-
216
- If the schema name "postgis" is included in the <i>schema_search_path</i>
217
- parameter, the PostGIS adapter omits it from a SQL structure dump. This
218
- can be useful to prevent PostGIS definitions from appearing in the dump
219
- as described below.
220
-
221
- === Dealing With PostGIS Definitions
222
-
223
- PostGIS adds many objects (types, functions, triggers, meta-information
224
- tables, and other elements) to a PostgreSQL database. These objects are
225
- required for PostGIS to do its magic, but they can be a hassle when you
226
- are managing a database using Rails and \ActiveRecord. For example:
227
-
228
- * Dumping the structure as sql (rake db:structure:dump) may include all
229
- the PostGIS definitions as well, cluttering your SQL dump.
230
- * Rake tasks that automatically create the test database (e.g. rake test)
231
- may fail or emit a number of errors, because PostGIS definitions are
232
- either missing from or being added twice to the test database.
233
-
234
- To deal with these issues, we recommend the following technique:
235
-
236
- * Set either <i>postgis_extension</i> or <i>script_dir</i> in both your
237
- development and test database configurations. This will cause the
238
- PostGIS Adapter to automatically add the PostGIS definitions and
239
- spatial references to your databases when rake db:create is run.
240
- * Include "postgis" in your <i>schema_search_path</i> for both your
241
- development and test databases. It is recommended that you include it
242
- as the <i>last</i> element, so that your application's tables don't get
243
- added to it by default. For example:
244
- schema_search_path: public,postgis
245
- The PostGIS Adapter responds to this special name by sandboxing the
246
- PostGIS definitions into it when rake db:create is run, and it omits
247
- this schema when running SQL structure dumps.
248
- * Provide a separate <i>su_username</i> and <i>su_password</i> role for
249
- your database, and make sure that separate role has the SUPERUSER
250
- privilege. This will cause the PostGIS Adapter to log in as that role
251
- when creating the database, since the PostGIS definition installation
252
- requires SUPERUSER. Alternately, you can give the normal database role
253
- SUPERUSER privilege, which may be okay for a private development
254
- database. These are used only by <tt>rake db:create</tt> so you can
255
- remove them from your database.yml for your staging or production
256
- databases once you've performed the initial creation.
257
-
258
- Finally, you generally should _not_ set the \ActiveRecord schema format
259
- to <tt>:sql</tt>. You should leave it set to <tt>:ruby</tt>. The reason
260
- is that SQL structure dumps do not currently properly emit the correct
261
- <tt>AddGeometryColumn</tt> calls to create geometry columns. As a result,
262
- the <tt>geometry_columns</tt> table will not be populated properly, among
263
- other issues. Instead, the schema.rb output by the Ruby schema format
264
- should properly replicate the schema. This is a known issue that we are
265
- investigating.
266
-
267
- Of course, the above steps are only really necessary if you are using the
268
- \ActiveRecord rake tasks that create databases, either directly such as
269
- <tt>rake db:create</tt>, or indirectly such as <tt>rake test</tt>. They
270
- should not be necessary for running migrations or normal website execution.
271
-
272
- == Additional Information
273
-
274
- === Known bugs and limitations
275
-
276
- The PostGIS Adapter has not yet been tested in a large variety of
277
- environments, and we are still fixing bugs. Here is a partial list of
278
- current known issues.
279
-
280
- * Dumping as SQL (i.e. rake db:structure:dump) does not properly emit
281
- <tt>AddGeometryColumn</tt> calls, and so does not completely create the
282
- spatial schema (e.g. it fails to add the proper row to the
283
- <tt>geometry_columns</tt> table.) Because of this, you should not depend
284
- on a SQL dump to be an accurate representation of the schema. (That is,
285
- you should not set <tt>config.active_record.schema_format</tt> to
286
- <tt>:sql</tt>.)
287
- * Other rake tasks may not be supported. Unfortunately, Rails makes it
288
- difficult for custom \ActiveRecord adapters to support the standard
289
- rake tasks.
290
- * Rails 4 is not yet supported. The good news is that the base PostgreSQL
291
- adapter has been refactored in Rails 4 to make it easier to extend, so
292
- once we get it ported to Rails 4, activerecord-postgis-adapter should
293
- be cleaner and more stable.
294
-
295
- === Development and support
296
-
297
- Documentation is available at http://dazuma.github.com/activerecord-postgis-adapter/rdoc
43
+ Please note that this adapter uses the rgeo gem, which may have additional dependencies. Please see the \README documentation for rgeo for more information.
44
+
45
+ Once you have installed the adapter, you'll need to edit your config/database.yml to call for it. At minimum, this means changing the adapter name from "postgresql" to "postgis". It may also require other settings to ensure that other functions (such as rake test) continue to work as expected. We recommend reading the Configuration section in the Documentation.rdoc file carefully before starting to use this adapter.
46
+
47
+ == Development and Support
48
+
49
+ \Documentation is available at http://dazuma.github.com/activerecord-postgis-adapter/rdoc
298
50
 
299
51
  Source code is hosted on Github at http://github.com/dazuma/activerecord-postgis-adapter
300
52
 
@@ -306,7 +58,7 @@ Support available on the rgeo-users google group at http://groups.google.com/gro
306
58
 
307
59
  Contact the author at dazuma at gmail dot com.
308
60
 
309
- === Acknowledgments
61
+ == Acknowledgments
310
62
 
311
63
  The PostGIS Adapter and its supporting libraries (including RGeo) are
312
64
  written by Daniel Azuma (http://www.daniel-azuma.com).
@@ -318,9 +70,9 @@ This adapter implementation owes some debt to the spatial_adapter plugin
318
70
  different design decisions for this adapter, studying the spatial_adapter
319
71
  source gave us a head start on the implementation.
320
72
 
321
- === License
73
+ == License
322
74
 
323
- Copyright 2010-2012 Daniel Azuma
75
+ Copyright 2010-2013 Daniel Azuma
324
76
 
325
77
  All rights reserved.
326
78