Lukas Z's Private Blog

(mostly about programming)

The Gist of GIS With MySQL and Ruby on Rails

I am currently working on a small prototype application that requires my rails app to store and process geospatial information. Basically, I am storing and querying longitude/latitude coordinates.

I have been working on projects that had similar use-cases before, but when I joined everything was set up already. Also, usually it was PostgreSQL with PostGIS. This time though, I had to do it myself and with MySQL.

So, since other people might have the same idea, I figured I’d put a few code snippets here so you can get started quicker.

First, here’s my Gemfile:

source ''

gem 'rails', '3.2.11' # you should update this to 3.2.13 now! ;)

gem 'mysql2'
gem 'spatial_adapter', :git => ""
gem 'geokit-rails3'

# ... some other gems here

This is how a migration might look like (I don’t think you still need the ENGINE=MyISAM line with a current MySQL version):

class CreatePoints < ActiveRecord::Migration
  def change
    create_table(:points, :options => 'ENGINE=MyISAM') do |t|
      t.string :name
      t.column :lat, :decimal, :precision => 15, :scale => 10
      t.column :lon, :decimal, :precision => 15, :scale => 10

I also added indexes on both decimal-fields.

And here is a bit from my model including two simple queries.

class Point < ActiveRecord::Base
  attr_accessible :lat, :lon, :name

  acts_as_mappable :default_units => :miles,
                   :default_formula => :sphere,
                   :distance_field_name => :distance,
                   :lat_column_name => :lat,
                   :lng_column_name => :lon

  def self.nearest_points( lat, lon )
                Point.within( 10, :origin => [lat, lon] ).order( "distance asc" )

  def self.at_point?( lat, lon )
                Point.within( 0.02, :origin => [lat, lon] ).order( "distance asc" ).first

  # ... etc.

Check out the geokit-rails3 README on Github for some examples.

I hope I just saved someone an hour or so of googling.

P.S.: You can follow me on Twitter.