GIS on Rails

by tokumine

There are times we want our Rails apps to have some sort of spatial capability. Recording lat long point locations and displaying them in a google map is fine, but increasingly we want to do more with our spatial data.

We want to be able to import data from a wide range of existing spatial filetypes such as shapefile or KML. We want to store complex spatial datatypes like multiple polygons with thousands of vertices in our databases with ease. We want to be able to convert spatial data between different projections and datums. We want to be able to run spatial queries like buffers, joins and intersects. We want to RESTfully output our spatial data in a variety of formats like AMF, geoJSON, KML and shapefile. We also want to output our data to our own set of raster tiles. Finally, we want to view our data in client side flash or javascript viewers.

Well, the Python web framework GeoDjango seems to do a lot of this.

GeoDjango… ok… Er, the title says Rails…

Why was awesome

There’s currently no equivalent pre-wrapped all-in-one GIS library like GeoDjango available for Rails. In addition to this, Rails core is fairly trim, and with Rails 3 is set to get even more focussed. It’s fair to predict that GIS features will never make it into Rails core in the same way GeoDjango has integrated with Django core.

This means that if you want to do feature rich GIS web apps with Rails, you’re gonna have to assemble the pieces yourself.

As it turns out, it’s pretty easy to assemble something similar.

What we can learn from GeoDjango?

GeoDjango is actually the collective name for a suite of existing open source GIS libraries, tools and database which have been integrated into the Django core framework. OSS web GIS takes very much a “stack” style approach, making it easy to draw out discreet functionality from GeoDjango, and look for equivalents in the Ruby world.

  • GEOS – spatial predicate functions and spatial operators
  • GDAL/OGR – amongst other things specializes in reading and writing geographic data
  • Model API – Allows spatial data types to be handled in Python objects
  • Database API – Allows spatial data types to be handled in Models, and also provides for spatial querying.

Tiling and the clientside code is currently handled outside the core GeoDjango stack, and the procedure (wiring a tile generator directly to PostGIS, and writing heavy client side visualisation code) is likely to be the same for Ruby apps. See GeoServer, and Mapnik for tips on tile generation, the google maps API for flash, or openlayers API for client side Viz.

How to replicate this back in Ruby/Rails land


The good thing is that it’s all possible. I’m assuming you’re using Postgres and the amazing PostGIS extension


For the core GeoDjango functionality, I’ve used a combination of GeoRuby, postgis_adapter libraries and straight PostGIS successfully. With these 3, most of the core GeoDjango plumbing can be replicated, and there are clear extension points where more functionality is needed.

Geospatial datatypes and file IO

GeoRuby provides native Ruby representations of the OGC basic datatypes, and basic Data IO. Note that it’s almost always better to either use the shp2pgsql command or plain GDAL/OGR for data loading purposes. I had issues with Shapefile attribute reading under Ruby 1.9.1 with GeoRuby.

Analysing the data

On the spatial query layer, Postgis_adapter and raw PostGIS SQL are your best bet. Postgis_adapter provides a basic wrapper for PostGIS spatial queries and is useful for quick one off’s, but it’s *almost always* best to drop to SQL (or other) for intensive & large spatial queries. The same would be true in GeoDjango, so we’re not losing much. Reprojections are handled by PostGIS.

Outputting the data

Finally, output is handled according to requirements. GeoRuby writes a variety of formats, (WKT, KML etc), PostGIS 1.4 outputs geoJSON natively, and AMF adaptors like Flails, RubyAMF, or WebORB allow for ultra fast connections to client apps for your spatial data.


Again, with the tiling and actual visualisation, GeoServer or Mapnik are good for tile generation, with the Google Maps API or OpenLayers being the best client side visualisation libraries available.


While I’ll leave most of the installations as an exercise to the reader until another post, if you are on OSX, you can install PostGIS easily via the lifesaving KyngChaos Binaries. That and GeoRuby+postgis_adapter should be enough to get you started.

Is that it? Sample app?

Sorry, not yet. But ping me on Twitter or the comments if you’d like to add to this, have questions or want to correct me. I’m sure I’ve got a bazillion things wrong, and would welcome any comments.