Latitude and Longitude Columns in Rails Migrations
Dec 29 by
Andre in
Google Maps »
,
Ruby on Rails »
So you're building a map application in Rails? Awesome. What datatypes are you going to use to store latitude and longitude in your database? There are three options:
Floats work, but their precision is limited. For example, if you geocode 101 Market st, San Francisco, you'll get latitude=-122.395899, longitude=37.793621. Store those values in the MySql table created by the above migration, and you'll get -122.396 and 37.7936 back out, thereby losing three decimal places of precision on your latitude. Still, they work fine if you're experimenting, and I use floats for some examples in my upcoming Rails/Gmaps book.
Much nicer! This doesn't work in 1.1.6 but was fixed in 1.2. The columns it generates is identical to the post-hoc ALTER TABLE we did earlier, but without the DB-specific ugliness or redundancy. By the way, see here if you want to learn about scale and precision in the DB.
1. Just use Floats.
This may be the first thing you try. The migration looks like this:class CreatePlaces < ActiveRecord::Migration
def self.up
create_table :places do |t|
t.column :lat, :float
t.column :lng, :float
end
end
def self.down
drop_table :places
end
end
Floats work, but their precision is limited. For example, if you geocode 101 Market st, San Francisco, you'll get latitude=-122.395899, longitude=37.793621. Store those values in the MySql table created by the above migration, and you'll get -122.396 and 37.7936 back out, thereby losing three decimal places of precision on your latitude. Still, they work fine if you're experimenting, and I use floats for some examples in my upcoming Rails/Gmaps book.
By the way, try this link if you want to see Google's XML output for geocoding this address. Yes, you can even use my personal Google API key embedded in this link -- I don't mind:
http://maps.google.com/maps/geo?q=101+market+st,94105.........
2. Alter a column using post-hoc SQL in your migration
Use this approach if you are running Rails 1.1.6, and need better precision than what Float provides. The migration looks like this:def self.upThis gives you full-on decimal precision, but now your migration is MySQL-specific and not very DRY. That's the breaks if you're on 1.1.6. You should really upgrade to Rails 1.2RCx and . . .
create_table :places do |t|
t.column :lat, :float
t.column :lng, :float
end
execute("ALTER TABLE places MODIFY lat numeric(15,10);")
execute("ALTER TABLE places MODIFY lng numeric(15,10);")
end
3. Use proper decimal-type migrations in Rails 1.2
def self.up
create_table :places do |t|
t.column "lat", :decimal, :precision => 15, :scale => 10
t.column "lng", :decimal, :precision => 15, :scale => 10
end
end
Much nicer! This doesn't work in 1.1.6 but was fixed in 1.2. The columns it generates is identical to the post-hoc ALTER TABLE we did earlier, but without the DB-specific ugliness or redundancy. By the way, see here if you want to learn about scale and precision in the DB.
Working with maps-based applications is interesting on a number of levels. One of the interesting aspects is the notion of Location versus the notion Locality.