Posts tagged ym4r
Comparing rails geo-plugins
Mar 4th
There seems to be quite a plethora of Ruby/Rails libraries appearing aiming to simplify handling geography and distances. In some cases these libraries do quite distinct things (zip codes vs. longitude/latitude, map output vs. distance calculations) but they’re frequently lumped together and it’s difficult to tell which will be best to use in your projects.
I’ve used several of these projects and have previously blogged about YM4R and acts_as_locateable, but I’m still not sure which I’d pick for new projects. So I thought it would be helpful to try to put together a comparison of which libraries offer what functionality. Here I’ll just offer a quick chart, but I’m hoping to write them up in a bit more detail over the coming days/weeks. If there’s sufficient interest, I’d consider moving this out to a wiki for more general use.
| Auto-geocoding ActiveRecord models | Multi-provider geo-coding | Distance based finds | Distance based :through finds | Google map output | Yahoo map output | |
|---|---|---|---|---|---|---|
| GeoKit (plugin index) |
Y | Y | Y | N | N | N |
|
acts_as_geocodable ( plugin index) |
Y | Y* | Y | N | N | N |
|
acts_as_geocode (plugin index) |
Website currently down | |||||
|
actsaslocateable (plugin index) |
N | N | Y | Y | N | N |
|
YM4R (plugin index) |
N | N | N | N | Y | Y |
(* through companion gem)
Also worth mentioning are SpatialAdapter and GeoRuby (from the same developer as YM4R) which respectively provide ActiveRecord support for MySql Spatial and PostGIS geometric columns, and ruby data types for that information.
A recent addition is this Ruby library for the Geonames API which provides a nice way to interface with the GeoNames database of 2.2 million populated places. Properly harnessed, that service begins to make it possible to allow your users to describe their location in natural language and convert that into machine-parseable co-ordinates.
Update (8th March): Updated versions of this comparison will now appear on the foss4r wiki
Update (October 2008): The chart now lives on a separate page within this site.
Auto Center and Zoom with YM4R
Oct 11th
When I blogged last month about abstracting mapping with YM4R I commented:
What I’ve not yet discovered (and may not be implemented) is a way to automatically center and zoom a map. It would be very nice to be able to add a batch of points to a map and have the plugin automatically work out their mid-point. Maybe I need to work on that a little…
What I was missing was the center_zoom_on_bounds_init method. There are various ways to interact with it, but I’ve chosen:
sorted_latitudes = locations.collect(&:latitude).compact.sort sorted_longitudes = locations.collect(&:longitude).compact.sort @map.center_zoom_on_bounds_init([ [sorted_latitudes.first, sorted_longitudes.first], [sorted_latitudes.last, sorted_longitudes.last]])
That mostly replaces the call to
@map.center_zoom_init([latitude, longitude], 14)
that I was previously using, though I’ve actually kept that around if there’s only one point as I was finding Google Maps’ maximum zoom didn’t show quite enough context for my tastes.
While it would be nice if the plugin had a method that performed the calculations based on the points you’ve fed in, it looks like the current implementation stores the points as javascript strings, so that’s not really an option. But with only three lines of code involved, this is a nice simple way to get the desired effect.
Abstracting mapping with YM4R
Sep 1st
When Grand Rapids WiFi–then a PHP application–first implemented google map support all the logic for producing those maps came in the templates. The controller passed the view a list of locations for that page, and it wrote out a series of javascript calls that produced the map. It was a little unreliable and very clunky, but it worked. When I moved the app over to rails, that was one aspect that I didn’t change, and it continued to work.
With more and more talk lately of google and lock-in, and some desire to begin to do more with the maps (perhaps invoking the ajax buzzword) I realised that I needed better tools and cleaner abstraction to work with the map. And it just so happened that YM4R_Mapstraction appeared at just the right time.
YM4R_Mapstraction is a rails plugin that provides methods to build map objects in your controller and helpers that will turn that into a map in the view. Controller code looks like:
@map = Mapstraction.new('map', :google) @map.control_init(:small => true) @map.center_zoom_init([location.latitude, location.longitude], 11) @map.marker_init(Marker.new([location.latitude, location.longitude], :label => location.name, :info_bubble => location.description))
and view code would be:
< %= Mapstraction.header(:google) %> < %= @map.to_html %>
in the header, and
< %= @map.div(:width => 300, :height => 300) %>
where you want your map to appear in the page.
To switch from a google map to a yahoo map, you simply need to replace ‘:google’ with ‘:yahoo’ in the examples above, opening up the possibility of automatically checking for server availability, or of allowing users to choose their preferred map.
One thing I found frustrating was simply having text for the description in the info bubble. That was easily solved by creating a partial called _bubble.rhtml and changing the marker code to:
@map.marker_init(Marker.new([location.latitude, location.longitude], :label => location.name, :info_bubble => render_to_string(:partial => 'bubble')))
So far, using the partials doesn’t seem to slow things down too much, but eventually I hope to cache the partials to reduce any overhead that might introduce.
What I’ve not yet discovered (and may not be implemented) is a way to automatically center and zoom a map. It would be very nice to be able to add a batch of points to a map and have the plugin automatically work out their mid-point. Maybe I need to work on that a little…