GPS-style Latitudes and Longitudes on Rails Forms
The Problem
Latitudes and Longitudes (credit: NASA)
Quite a few plugins exist to help you geocode post codes or zipcodes, and calculate the distance between two points. However few, if any, help you with latitudes and longitudes on forms, with input elements that match your GPS, and intelligent validation.
This is now solved.
The Situation
I’m building a web application that holds cruising information for offshore sailors. Much of the information is located, in the sense that it applies to a specific point on the Earth’s surface. A report on an anchorage, for example, might say something like, “Beware the submerged rock to starboard at the entrance; strong katabatic winds in spring; herds of wildebeest ashore.” So we need the sailors to supply latitudes and longitudes on most of the forms they fill in.
The only way to travel (credit: Horse’s Mouth)
The consensus among existing geo plugins is to treat latitudes and longitudes as floats, storing them in the database as decimals. However that’s not how people handle latitudes and longitudes. For excellent historical reasons, we think in degrees, minutes and seconds. Or, if you use a GPS — and all sailors do — degrees, minutes and decimal minutes (milli-minutes).
If you want people to enter the latitude and longitude of an anchorage on your site, and to enter them correctly, you need to let them just read it off their GPS. And if they enter an invalid value, you need to flag whether it’s the degrees, the minutes, or the milli-minutes — not simply say the whole lot “is invalid”.
The Solution
Buy the Rails 2 Plugin Patterns Peepcode PDF. Using the PDF I was able to write the plugin right, first-time. No trial and error: straight to the solution. The time it saved was more than worth $9. And the author’s a great guy ;-)
So, install my GeoTools plugin:
$ script/plugin install git://github.com/airblade/geo_tools.git
(I’ll move all my plugins to Git soon, but they’ll remain available in Subversion for the forseeable future.)
Run a database migration to add latitudes and longitudes to the relevant tables. Let’s say we are talking about buried treasure:
def self.up
create_table :treasures do |t|
t.string :name
t.boolean :display_on_map, :default => true
t.with_options :precision => 15, :scale => 10 do |c|
c.decimal :latitude
c.decimal :longitude
end
t.timestamps
end
end
Show me the treasure
Note we store latitudes and longitudes in the conventional way, so you can use other geo plugins too.
Tell your models what to do:
class Treasure < ActiveRecord::Base
acts_as_location
end
Add latitude and longitude fields to your forms:
<% form_for @treasure do |f| %>
<p>
<label for='treasure_name'>Name</label>
<%= f.text_field :name %>
</p>
<p>
<label for='treasure_display_on_map'>Display on map?</label>
<%= f.check_box :display_on_map %>
</p>
<p>
<label for='treasure_latitude'>Latitude</label>
<%= f.latitude_field :latitude %>
</p>
<p>
<label for='treasure_longitude'>Longitude</label>
<%= f.longitude_field :longitude %>
</p>
<% end %>
Done.
You can also easily display a latitude and longitude:
<p>Name: <%=h @treasure.name %></p>
<p>Location: <%= @treasure.location %></p>
And that will produce:
<p>Name: King Solomon's Mines</p>
<p>Location: 12°34.567′S, 98°76.543′W</p>
Bonus
Happily for you, my AirBudd accessible form builder plugin is fully compatible with GeoTools. So instead of the form shown above, you can write this:
<% airbudd_form_for @treasure do |f| %>
<%= f.text_field :name %>
<%= f.check_box :display_on_map %>
<%= f.latitude_field :latitude %>
<%= f.longitude_field :longitude %>
<% end %>
And that’s compatible with HAML too.
So now we have meaningful, GPS-style latitudes and longitudes with minimal effort. And treasure.
Posted in Client Work, Rails

4 Comments
Jump to comment form