PostGIS ActiveRecord Adapter

The PostGIS ActiveRecord Adapter is an ActiveRecord connection adapter based on the standard postgresql adapter. It extends the standard adapter to provide support for the spatial extensions provided by PostGIS, using the RGeo library to represent spatial data in Ruby. Like the standard postgresql adapter, this adapter requires the pg gem.

What This Adapter Provides

Spatial Migrations

First, this adapter extends the migration syntax to support creating spatial columns and indexes. To create a spatial column, use the :geometry type, or any of the OGC spatial types such as :point or :line_string to set a geometry type constraint. You may also provide any of the following options:

To create a spatial index, set the :spatial option to true when creating the index.

Examples:

create_table :my_spatial_table do |t|
  t.column :shape, :geometry  # or t.geometry :shape
  t.line_string :path, :srid => 3785
  t.point :latlon, :geographic => true
end
change_table :my_spatial_table do |t|
  t.index :latlon, :spatial => true
end

Spatial Attributes

When this adapter is in use, spatial attributes in your ActiveRecord objects will have RGeo geometry values. You can set spatial attributes either to RGeo geometry objects, or to strings in WKT (well-known text) format, which the adapter will automatically convert to geometry objects.

Spatial objects in RGeo are tied to a factory that specifies the coordinate system as well as other behaviors of the object. You must therefore specify a factory for each spatial column (attribute) in your ActiveRecord class. You can either set an explicit factory for a specific column, or provide a factory generator that will yield the appropriate factory for the table’s spatial columns based on their types. For the former, call the set_rgeo_factory_for_column class method on your ActiveRecord class. For the latter, set the rgeo_factory_generator class attribute. This generator should understand the usual :srid, :has_z_coordinate, and :has_m_coordinate options. It will also be passed a :geographic option indicating whether the column is a geography column. The set_rgeo_factory_for_column and rgeo_factory_generator methods are actually implemented and documented in the “rgeo-activerecord” gem.

Examples, given the spatial table defined above:

class MySpatialTable < ActiveRecord::Base

  # By default, use the GEOS implementation for spatial columns.
  self.rgeo_factory_generator = RGeo::Geos.factory_generator

  # But use a geographic implementation for the :latlon column.
  set_rgeo_factory_for_column(:latlon, RGeo::Geographic.spherical_factory)

end

Now you can interact with the data using the RGeo types:

rec = MySpatialTable.new
rec.latlon = 'POINT(-122 47)'   # You can set by feature object or WKT.
loc = rec.latlon                # Accessing always returns a feature object, in
                                # this case, a geographic that understands latitude.
loc.latitude                    # => 47
rec.shape = loc                 # the factory for the :shape column is GEOS, so the
                                # value will be cast from geographic to GEOS.
RGeo::Geos.is_geos?(rec.shape)  # => true

Spatial Queries

You can create simple queries based on objective equality in the same way you would on a scalar column:

rec = MySpatialTable.where(:latlon => RGeo::Geos.factory.point(-122, 47)).first

You can also use WKT:

rec = MySpatialTable.where(:latlon => 'POINT(-122 47)').first

The adapter also provides experimental support for more complex queries such as radius searches. However, these extensions require Arel 2.1 (which is scheduled for release with Rails 3.1). We do not have these documented yet, and the syntax is subject to change. For now, you should write more complex queries in SQL.

Installation And Configuration

Installing The Adapter Gem

This adapter has the following requirements:

Install this adapter as a gem:

gem install activerecord-postgis-adapter

See the README for the “rgeo” gem, a required dependency, for further installation information.

Basic Setup

To use this adapter, add this gem, “activerecord-postgis-adapter”, to your Gemfile, and then request the adapter name “postgis” in your database connection configuration (which, for a Rails application, is in the config/database.yml file). Most of the rest of the configuration parameters are identical to those used by the stock “postgresql” adapter, so you can create a new Rails application using:

rails new my_app --database=postgresql

…and then just change the adapter name to “postgis”.

Next, the PostGIS adapter includes a special railtie that provides support for PostGIS databases in ActiveRecord’s rake tasks. This railtie is required in order to run, e.g., rake test. To install this railtie, you should add this line to your config/application.rb:

require 'active_record/connection_adapters/postgis_adapter/railtie'

Note that this railtie must load after the ActiveRecord railtie. That is, the above require command should appear after require 'rails/all'.

Besides the adapter name “postgis”, most of the other database connection configuration parameters are the same as for the stock postgresql adapter. However, there are several important differences:

The script_dir parameter is specific to the PostGIS adapter, and provides the path to the directory containing the SQL scripts for PostGIS installation. This directory should contain the files postgis.sql and spatial_ref_sys.sql. (A common setting for this directory might be /usr/local/share/contrib/postgis-1.5.) It is used by rake db:create to add the PostGIS types, functions, and tables to a newly created database. If you do not provide this parameter, you will need to add these objects to the database manually. Generally, therefore, this parameter is required at least for the test database, which is usually automatically created by the rake tasks.

The su_username and su_password parameters are provided as optional parameters. If present, they specify an auxiliary PostgreSQL role that must have superuser privileges, and will be used for two functions:

Any schemas listed in the schema_search_path parameter are automatically created by rake db:create. This is arguably what the stock PostgreSQL adapter should be doing anyway.

If the schema name "postgis" is included in the schema_search_path parameter, the PostGIS adapter omits it from a SQL structure dump. This can be useful to prevent PostGIS definitions from appearing in the dump as described below.

Dealing With PostGIS Definitions

PostGIS adds many objects (types, functions, triggers, meta-information tables, and other elements) to a PostgreSQL database. These objects are required for PostGIS to do its magic, but they can be a hassle when you are managing a database using Rails and ActiveRecord. For example:

To deal with these issues, we recommend the following technique:

Finally, you generally should not set the ActiveRecord schema format to :sql. You should leave it set to :ruby. The reason is that SQL structure dumps do not currently properly emit the correct AddGeometryColumn calls to create geometry columns. As a result, the geometry_columns table will not be properly populated, among other issues. Instead, the schema.rb output by the Ruby schema format should properly replicate the schema. This is a known issue that we are investigating.

Of course, the above steps are only really necessary if you are using the ActiveRecord rake tasks that create databases, either directly such as rake db:create, or indirectly such as rake test. They should not be necessary for running migrations or normal website execution.

Additional Information

Known bugs and limitations

The PostGIS Adapter has not yet been tested in a large variety of environments, and we are still fixing bugs. Here is a partial list of current known issues.

Development and support

Documentation is available at virtuoso.rubyforge.org/activerecord-postgis-adapter/README_rdoc.html

Source code is hosted on Github at github.com/dazuma/activerecord-postgis-adapter

Contributions are welcome. Fork the project on Github.

Report bugs on Github issues at github.org/dazuma/activerecord-postgis-adapter/issues

Support available on the rgeo-users google group at groups.google.com/group/rgeo-users

Contact the author at dazuma at gmail dot com.

Acknowledgments

The PostGIS Adapter and its supporting libraries (including RGeo) are written by Daniel Azuma (www.daniel-azuma.com).

Development of RGeo is sponsored by GeoPage, Inc. (www.geopage.com).

This adapter implementation owes some debt to the spatial_adapter plugin (github.com/fragility/spatial_adapter). Although we made some different design decisions for this adapter, studying the spatial_adapter source gave us a head start on the implementation.

License

Copyright 2010-2011 Daniel Azuma

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

[Validate]

Generated with the Darkfish Rdoc Generator 2.