Posts tagged plugins

Selected (belated, extended) Saturday Links

The past two weeks haven’t really left time to compile my selected links, though there have been many. A few days at SxSWi (on which more, later) followed by travelling with the family and the inevitable work backlog moved blogging way down the priority list. So here’s a mammoth selection to get me caught up. Particularly interesting has been the discussion around the future of newspapers (represented here by Clay Shirky, Steven Johnson and Russell Davies), which seem to have finally pushed beyond “how t ind a good business model for papers” to looking at where the real value for society lies and how we can preserve and extend that in a changing landscape.

Hacking wordpress to support per-post banner images

post-bannersI seem to be spending a lot of time with wordpress at the moment. It’s become so ubiquitous that it often makes far more sense to set it up and integrate with an existing app than to set up some other blogging system and re-train users. As a result I’ve been writing a few wordpress plugins. Most of them are too specialised to be worth sharing, but one seemed worth opening up…

Implementing a (not quite public yet) design recently I had need of a way to specify a banner image for each post. While wp has pretty good support for adding various media into the body of posts, this needed to sit outside the post body.

I whipped together a quick plugin to handle uploading a banner and storing its details in the metadata for the post. It was a simple process, nicely self-contained, except that the post edit form doesn’t have the appropriate enctype=”multipart/form-data”. I looked around for any hooks that would allow me to cleanly add attributes to the form tag, but in the end resorted to editing wp-admin/edit-form-advanced.php to add it.

I’d hoped that there’d be time to find a cleaner way to do all this before telling people about it—perhaps some javascript that hooks into the existing media selector but allows it to populate a custom data field?—but it hasn’t, so I’m throwing it out there to the wider world as-is. The code is at github. Feel free to take it and use it as-is, to fork it and update it to be a better wordpress citizen, to email me patches to apply to my copy, or even to employ me to spend more time cleaning it up! Either way, it deserves to be out in the open and hopefully it’ll be of us to somebody besides me.

New home for Rails ‘geo plugin comparison’

About eighteen months ago I compiled a series of reviews of Ruby on Rails plugins concerned with geography. I put together a comparison chart and posted it on this blog. It subsequently found a new home on a wiki, but lately that wiki has rarely been accessible so I decided it was time to move it all back into this site.

You can now find the comparison chart at: http://jystewart.net/process/resources/rails-geo-plugins/

A few updates have been lost along the way as they were solely made on the wiki, but hopefully it’s still of use. Since I published the original reviews and chart my attention has wandered a little from the geo plugin scene, so please do flag up any new plugins, changes in features or fixes that I may have missed. I’m going to be trying to check through all the existing listings to update them but that may take a while, so comments here may well encourage me to focus more quickly.

Rails Geo Plugins: GeoX

GeoX is the latest kid on the Ruby on Rails geocoding block. The plugin was announced a couple of weeks ago and I’ve been meaning to explore it ever since, just in case it had any new features and also so that I can add it to my comparison chart.

The feature set of GeoX is fairly straightforward. It supports a number of geocoding back ends: obviously google and yahoo are covered, but also mapquest’s relatively recent API. The standard lookup process is much like that provided by several other plugins—the sample given is:

require 'geox'
 
# uses the google engine
geocoder = GeoX::Geocoder.new(:geoengine => GeoX::Google) 
location = {:address => '701 Ocean St', :post_code => '95060'}
geocode = geocoder.geocode(location)
 
# geocode will be a hash containing the geocode data returned from the server
puts geocode.inspect

What is most notably lacking is any ActiveRecord integration such as that offered by acts_as_locateable or acts_as_geocodable. That is apparently by design as the intention is for the library to be usable outside rails but the plugin relies on the rails-specific blank? method and personally I prefer the graticule/acts_as_geocodable split where functionality equivalent to that of GeoX is bundled in the graticule gem and then ActiveRecord hooks are provided by the plugin. It is definitely nice to have geocoding handled manually when models are added or updated, but more than that it is very useful to have support provided for searching based on location.

Probably the most intriguing aspect of the plugin is the facility to compare the specificity of two different sets of coordinates. That’s achieved by returning an object type appropriate to the specificity. So if you have street-level data, the object returned is an instance of GeoX::Street. Operator overloading allow you to compare the objects:

puts "Street wins!" if GeoX::Street.new < GeoX::Block.new

The README file suggests putting the API keys in the file lib/geox_api_keys.rb within the plugin. That’s probably not the best of ideas, but it would be easy enough to rework it so that the configuration is done in the usual rails way and the plugin can be included with svn:externals or piston.

I can’t see myself switching to GeoX from the options I currently use and it’s a shame that its distinctive features weren’t submitted as patches to existing projects rather than adding yet another plugin to the increasingly crowded scene, but it’ll be interesting to see how it evolves over the coming months.

Rails Geo Plugins: GeoKit

There’s quite a bit of overlap between GeoKit and acts_as_geocodable/graticule, as the latter pair were based on GeoKit. But it provides at least one feature (IP-based location lookup) that they don’t, so I decided to give it a whirl.

Since my main geographically related projects are both now based on plugins that I’m pretty happy with and which suit them well, I decided to resuscitate an old sample piece. A few months back I wrote about scraping the Grand Rapids bus routes site and put up a toy application utilising the resource features in then-edge Rails. I’ve been meaning to return to that project to test out some features in ActiveResource, but in the meantime it seemed like it might be useful to be able to search for the nearest bus stop.

The plugin comes with an extensive README file and getting up and running is very straightforward:

class BusStop < ActiveRecord::Base
	acts_as_mappable :default_units => :kms, 
		:default_formula => :flat, 
		:distance_field_name => :distance,
		:lng_column_name => 'longitude', :lat_column_name => 'latitude'

I had to add the column_name parameters to signify which database columns I was using, as the plugin defaults to using ‘lat’ and ‘lng’ for brevity. The inclusion of the default_units parameter is a nice one, but it would also be nice if the plugin provided an accessor method to convert distance on the fly to help developers localise their apps.

With that done I get access to a suite of methods for doing location searches. So if I wanted to find the nearest bus stop to Common Ground Coffee Shop I could call:

BusStop.find(:nearest, 
	:origin => '1319 Fulton St. East, Grand Rapids MI 49503')

That address actually failed in the google geocoder (probably because I had yet to enter my api key), but GeoKit automatically fell back to geocoder.us and got the co-ordinates.

Where it seemed to fall over was when I tried to limit by bus route:

BusStop.find(:nearest, :origin => '1319 Fulton St. East, Grand Rapids MI 49503',
	:include => :route_stops, 
	:conditions => 'route_stops.bus_route_id = 6')
 
ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'distance' in 'field list': SELECT DISTINCT bus_stops.id, distance FROM bus_stops  LEFT OUTER JOIN route_stops ON route_stops.bus_stop_id = bus_stops.id WHERE (route_stops.bus_route_id = 6) ORDER BY distance ASC  LIMIT 1

Andre Lewis, one of the plugin’s developers (along with Bill Eisenhauer), tells me that GeoKit doesn’t currently support the :include option or conditions on join tables. He’s hoping to add that soon, but for now you’re limited to a single table.

Implementing the IP-based geolocation was very easy. A before_filter is included which can be included in a controller with the declaration:

geocode_ip_address

will return a GeoLoc object containing details of the lookup source, the address and the co-ordinates. I chose to add my own before_filter so I could find the nearest bus stop:

class ApplicationController < ActionController::Base
  before_filter :find_nearest_stop
 
  def find_nearest_stop
    @nearest = BusStop.find_nearest(:origin => get_ip_address)
  end
end

(where get_ip_address is a method provided by the plugin). I had to deploy to a remote host to actually test this as 127.0.0.1 obviously doesn’t work as a source IP address for these purposes, and it’s likely that a number of users working through proxies of one sort or another will find the information less than accurate. But so long as that’s clear, it’s a nice feature to add to local information services, potentially getting users to relevant information more quickly.

I do like the separation between gem and plugin that acts_as_locateable offers, the fact that geocodes are stored in a separate table, and full join support for queries. But the IP translation from GeoKit is also a nice feature. Both are highly capable solutions, so it’s likely that once GeoKit adds full join support, choosing between them may well come down to personal taste.

(Nb. Those following along with these posts may be interested in GeoKit co-author Andre Lewis’ book Beginning Google Maps Applications with Rails and Ajax. I’m hoping to check it out soon)