<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>a work on process &#187; plugins</title>
	<atom:link href="http://jystewart.net/process/tag/plugins/feed/" rel="self" type="application/rss+xml" />
	<link>http://jystewart.net/process</link>
	<description>notes from another web developer</description>
	<lastBuildDate>Tue, 27 Jul 2010 09:53:43 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Selected (belated, extended) Saturday Links</title>
		<link>http://jystewart.net/process/2009/03/selected-belated-extended-saturday-links/</link>
		<comments>http://jystewart.net/process/2009/03/selected-belated-extended-saturday-links/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 20:40:20 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Notes]]></category>
		<category><![CDATA[acquia]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[activitystreams]]></category>
		<category><![CDATA[analysis]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[bdd]]></category>
		<category><![CDATA[business]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[clayshirky]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[context]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[dopplr]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[edemocracy]]></category>
		<category><![CDATA[engines]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[fireeagle]]></category>
		<category><![CDATA[flickr]]></category>
		<category><![CDATA[fonts]]></category>
		<category><![CDATA[foursquare]]></category>
		<category><![CDATA[fridayblog]]></category>
		<category><![CDATA[future]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[gem]]></category>
		<category><![CDATA[geo]]></category>
		<category><![CDATA[guardian]]></category>
		<category><![CDATA[heroku]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[ilife]]></category>
		<category><![CDATA[interactiondesign]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[iphoto]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[localgovernment]]></category>
		<category><![CDATA[location]]></category>
		<category><![CDATA[mapping]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[mattjones]]></category>
		<category><![CDATA[media]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[nestedforms]]></category>
		<category><![CDATA[newspaper]]></category>
		<category><![CDATA[newspapers]]></category>
		<category><![CDATA[nigeria]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[ogs]]></category>
		<category><![CDATA[opengovernment]]></category>
		<category><![CDATA[openness]]></category>
		<category><![CDATA[openplatform]]></category>
		<category><![CDATA[panels]]></category>
		<category><![CDATA[passenger]]></category>
		<category><![CDATA[pecl]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[planning]]></category>
		<category><![CDATA[planningalerts]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[podcasts]]></category>
		<category><![CDATA[Rack]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rails2.3]]></category>
		<category><![CDATA[reflection]]></category>
		<category><![CDATA[releases]]></category>
		<category><![CDATA[revolution]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubyonrails]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[setup]]></category>
		<category><![CDATA[shoulda]]></category>
		<category><![CDATA[sinatra]]></category>
		<category><![CDATA[socialgraph]]></category>
		<category><![CDATA[socialnetworking]]></category>
		<category><![CDATA[socialweb]]></category>
		<category><![CDATA[solr]]></category>
		<category><![CDATA[sprinkle]]></category>
		<category><![CDATA[stevenberlinjohnson]]></category>
		<category><![CDATA[sxsw]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[toys]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[videogames]]></category>
		<category><![CDATA[vps]]></category>
		<category><![CDATA[walledgarden]]></category>
		<category><![CDATA[wireframes]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/?p=613</guid>
		<description><![CDATA[The past two weeks haven&#8217;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&#8217;s a mammoth selection to get me caught up. <a href="http://jystewart.net/process/2009/03/selected-belated-extended-saturday-links/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>The past two weeks haven&#8217;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&#8217;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 &#8220;how t ind a good business model for papers&#8221; to looking at where the real value for society lies and how we can preserve and extend that in a changing landscape.</p>
<ul class="link-list">
<li>
<h3><a href="http://www.learningjquery.com/2009/03/making-a-jquery-plugin-truly-customizable">Making a jQuery Plugin Truly Customizable » Learning jQuery &#8211; Tips, Techniques, Tutorials</a></h3>
<p>Some nice tips for managing options, and a reminder to find _useful_ customisations not just load with customisation options without much thought about/consultation with other potential users</p>
</li>
<li>
<h3><a href="http://www.slideshare.net/mattb/iphone-coding-for-web-developers">iPhone Coding For Web Developers</a></h3>
<p>Presentation slides from the internet&#039;s Matt Biddulph</p>
</li>
<li>
<h3><a href="http://www.brynary.com/2009/3/5/rack-test-released-a-simple-testing-api-for-rack-based-frameworks-and-apps">Rack::Test released: Simply test any Rack-compatible app — Bryan Helmkamp</a></h3>
<p>There&#039;s a _lot_ to like about increased adoption of rack. &quot;With Rack::Test, we hope to make it easy for frameworks to encourage their users to write tests by making it trivial to provide a testing environment. We’d like to foster compatibility between Ruby web app testing environments (especially important as ideas like multi-framework apps become more prominent). The philosophy is the library should stay small and extendable so frameworks can layer on additional functionality they want to offer without modifying Rack::Test’s core behavior or resorting to monkeypatching.&quot;</p>
</li>
<li>
<h3><a href="http://www.shirky.com/weblog/2009/03/newspapers-and-thinking-the-unthinkable/">Newspapers and Thinking the Unthinkable « Clay Shirky</a></h3>
<p>&quot;That is what real revolutions are like. The old stuff gets broken faster than the new stuff is put in its place. The importance of any given experiment isn’t apparent at the moment it appears; big changes stall, small changes spread. Even the revolutionaries can’t predict what will happen &#8230;. Ancient social bargains, once disrupted, can neither be mended nor quickly replaced, since any such bargain takes decades to solidify.&quot; &#8230; and a a lot more</p>
</li>
<li>
<h3><a href="http://russelldavies.typepad.com/planning/2009/03/newspapers-and-that.html">russell davies: newspapers and all that</a></h3>
<p>&quot;If we are going to create a new news ecosystem involving advertisers (and a lot of people would be grateful for that money) then we&#039;re going to have to do something about that institutional bifurcation between content and commerce.  We&#039;re going to have to design the relationship between the two with the care of a good experience designer.&quot; &#8211; a response to Ben Hammersley asking if anyone talking about the future of newspapers had talked to anyone in advertising</p>
</li>
<li>
<h3><a href="http://laughingmeme.org/2009/03/18/streams-affordances-facebook-and-rounding-errors/#footer">Streams, affordances, Facebook, and rounding errors &#8211; Laughing Meme</a></h3>
<p>&quot;Simon Willison asked this week about best practice for architecting activity streams. And the answer is, “It depends.” Depends on the scope, scale, access patterns, and affordances you’re building — your contract with your users.</p>
<p>Which is a long way of saying think hard about the promises you make to your users, implicitly or explicitly.</p>
<p>And, Facebook, my friend, what the HELL are you thinking? You managed to negotiate the best deal in the business, talk about a racket, and you threw it away for a piece of Twitter’s pain? Are you stupid? Well, best of luck with that.&quot;</p>
</li>
<li>
<h3><a href="http://sxsw.com/interactive/news/videos_and_podcasts">SXSW Interactive Videos and Podcasts | SXSW.com</a></h3>
<p>Most of the sessions were recorded and this is the place to get hold of them.</p>
</li>
<li>
<h3><a href="http://www.guardian.co.uk/technology/2009/mar/19/sxswi-texas-internet-trends-are-location-social-networking">SXSWi: Location-based service is the trend at Austin, Texas |</a></h3>
<p>&quot;Predictably, location-based services were a major feature this year, with launches that included Foursquare, a social, location-based game by the Dodgeball creator, Dennis Crowley, and a new Facebook application for the location management tool Fire Eagle. While early adopters such as the SXSWers have been exploring location-based services for some time, it is inevitable that more consumer and privacy-friendly versions will start to creep into the mainstream.&quot;</p>
</li>
<li>
<h3><a href="http://www.stevenberlinjohnson.com/2009/03/the-following-is-a-speech-i-gave-yesterday-at-the-south-by-southwest-interactive-festival-in-austiniif-you-happened-to-being.html">stevenberlinjohnson.com: Old Growth Media And The Future Of News</a></h3>
<p>&quot;I think it’s much more instructive to anticipate the future of investigative journalism by looking at the past of technology journalism. When ecologists go into the field to research natural ecosystems, they seek out the old-growth forests, the places where nature has had the longest amount of time to evolve and diversify and interconnect. They don’t study the Brazilian rain forest by looking at a field that was clear cut two years ago.&quot; &#8230; and &#8230;&quot; Measured by pure audience interest, newspapers have never been more relevant. If they embrace this role as an authoritative guide to the entire ecosystem of news, if they stop paying for content that the web is already generating on its own, I suspect in the long run they will be as sustainable and as vital as they have ever been. The implied motto of every paper in the country should be: all the news that’s fit to link.&quot;</p>
</li>
<li>
<h3><a href="http://highearthorbit.com/on-running-a-panel/">On running a panel</a></h3>
<p>A mixup over bus times meant I didn&#039;t make it to Andrew&#039;s panel at SxSW, but I heard many good things. It&#039;s really great to see this kind of debriefing-in-public going on. Hopefully it&#039;ll make for a stronger set of talks and panels next year.</p>
</li>
<li>
<h3><a href="http://guardian.apimaps.org/">Guardian API Maps &#8211; Home</a></h3>
<p>&quot;This is a site that lets you search the Guardian&#039;s new API and add location information to articles. All the place data we collect is being made available to anyone who wants it.&quot;</p>
</li>
<li>
<h3><a href="http://www.observer.com/2009/media/foursquare-hot-new-phone-app-dodgeball-steroids">Foursquare, Hot New Phone App, Is Dodgeball on Steroids | The New York Observer</a></h3>
<p>Quite a few people seemed to be playing with Foursquare at SxSW but most of the Brits were excluded as we didn&#039;t want to use that much data and it wasn&#039;t available in the UK iTunes store. One to watch, though.</p>
</li>
<li>
<h3><a href="http://simonwillison.net/2009/Mar/10/openplatform/">A few notes on the Guardian Open Platform</a></h3>
<p>I saw Simon present the Guardian Platform at SxSW and it looks like a great achievement. Waiting to see what developers build on it, and how they roll some of the ideas back in</p>
</li>
<li>
<h3><a href="http://highearthorbit.com/taking-remote-imagery-offline-to-nigeria/">Taking remote imagery offline to Nigeria  ::  High Earth Orbit</a></h3>
<p>Andrew&#039;s notes on trying to source good map data for use in Nigeria. It&#039;s a useful overview of a variety of services and ways to use them, though highlighting the absence of really accessible, high-quality data.</p>
</li>
<li>
<h3><a href="http://schulzeandwebb.com/blog/2009/03/03/the-utility-of-the-unfinished/">Pulse Laser: The Utility of the Unfinished</a></h3>
<p>&quot;One technique that S&amp;W has been using recently to illustrate design work is placing sketches or wireframes in situ. Whilst wireframes themselves are incomplete artefacts, designed to be work in progress, they still suffer for being uniformly incomplete. Wireframes themselves can be almost too beautiful, and this means that it becomes all-too-easy to criticise them as only wireframes, rather than as part of a product that exists in the world. Contextualising the sketches into the photograph places the design into the world. This enables the design to be understood within the world, and also (importantly) to highlight the seams between the unfinished design and the finished world around it&quot;</p>
</li>
<li>
<h3><a href="http://lucidmac.com/products/spike">Spike: a log file viewing &amp; (if we’re being generous) analysis tool for Rails developers.</a></h3>
<p>Looks like a handy addition to the toolkit</p>
</li>
<li>
<h3><a href="http://factoryjoe.com/blog/2009/03/04/generation-open/">Generation Open | FactoryCity</a></h3>
<p>&quot;Sharing and giving away all that you can are the best defenses against fear, obsolescence, growing old, and, even, wrinkles. It isn’t always easy, but it’s how we outlive the shackles of biology and transcend the physicality of gravity.&quot; &#8211; Perhaps an overly optimistic piece, but it connects together a number of current themes and we can hope&#8230;</p>
</li>
<li>
<h3><a href="http://opensoul.org/2009/3/6/testing-facebook-with-cucumber">Testing Facebook with Cucumber | opensoul.org</a></h3>
<p>For those faced with the unpleasant task of writing facebook apps, some people are working on making sure they can be thoroughly tested.</p>
</li>
<li>
<h3><a href="http://scraplab.net/2009/03/04/instant-sinatra-deployment-with-heroku.html">scraplab : instant sinatra deployment with heroku</a></h3>
<p>A lot of people seem to be excited about heroku lately, and it does look like a nice simple way to put up quick ruby apps. Must play soon.</p>
</li>
<li>
<h3><a href="http://buddingrubyist.com/2009/02/14/how-to-speed-up-gem-installs-10x/">How to speed up gem installs 10x « The Budding Rubyist</a></h3>
<p>Handy little tip, particularly for server environments: turn off ri and rdoc generation in your .gemrc file, and speed things up considerably</p>
</li>
<li>
<h3><a href="http://radar.oreilly.com/2009/03/facebook-in-2010-no-longer-a-walled-garden.html">Facebook in 2010: no longer a walled garden &#8211; O&#039;Reilly Radar</a></h3>
<p>A more positive spin on facebook&#039;s changes from David O&#039;Recordon, who suspects they&#039;re going to pull down the walls around their garden and become a proper citizen of the open web.</p>
</li>
<li>
<h3><a href="http://broadstuff.com/archives/1596-Facebook-blinks,-copies-Twitter,-still-gets-it-wrong..html">Facebook blinks, copies Twitter, still gets it wrong.  &#8211; broadstuff</a></h3>
<p>Critical commentary on facebook&#039;s recent changes. I&#039;m not sure I entirely agree with statements like &quot;By 2009 it was clear no one gives a sh*t about the Social Graph&quot; but facebook really do seem to be finding that their approach is overly complex and quickly trying to shift to a more twitter-like &quot;web of flow&quot; (to steal Stowe Boyd&#039;s phrase)</p>
</li>
<li>
<h3><a href="http://acquia.com/blog/acquia-search-goes-public-beta">Acquia Search goes public beta | Acquia</a></h3>
<p>Hosted solr for drupal: &quot;Acquia Search can be installed as a module on any Drupal 6 site, and enhances a site&#039;s search experience with faceted search navigation, content recommendations, and configurable results weighting, all delivered through a redundant hosted service infrastructure.&quot;.</p>
</li>
<li>
<h3><a href="http://pastie.org/405656">Oauth using pecl/OAuth</a></h3>
<p>Looks like a nice simple way to interact with oauth from a PHP app</p>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2009/03/selected-belated-extended-saturday-links/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hacking wordpress to support per-post banner images</title>
		<link>http://jystewart.net/process/2009/02/hacking-wordpress-to-support-per-post-banner-images/</link>
		<comments>http://jystewart.net/process/2009/02/hacking-wordpress-to-support-per-post-banner-images/#comments</comments>
		<pubDate>Mon, 23 Feb 2009 13:34:46 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[banner images]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[onlyconnect]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/?p=594</guid>
		<description><![CDATA[I seem to be spending a lot of time with wordpress at the moment. It&#8217;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&#8217;ve been writing a few wordpress <a href="http://jystewart.net/process/2009/02/hacking-wordpress-to-support-per-post-banner-images/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://jystewart.net/process/wp-content/uploads/2009/02/post-banners.png" alt="post-banners" title="post-banners" width="200" height="201" class="alignleft size-full wp-image-597" />I seem to be spending a lot of time with <a href="http://wordpress.org/" title="WordPress &#8250; Blog Tool and Publishing Platform">wordpress</a> at the moment. It&#8217;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&#8217;ve been writing a few wordpress plugins. Most of them are too specialised to be worth sharing, but one seemed worth opening up&#8230;</p>
<p>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.</p>
<p>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&#8217;t have the appropriate enctype=&#8221;multipart/form-data&#8221;. 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.</p>
<p>I&#8217;d hoped that there&#8217;d be time to find a cleaner way to do all this before telling people about it&#8212;perhaps some javascript that hooks into the existing media selector but allows it to populate a custom data field?&#8212;but it hasn&#8217;t, so I&#8217;m throwing it out there to the wider world as-is. <a href="http://github.com/jystewart/wordpress-post-banners/tree/master" title="jystewart's wordpress-post-banners at master - GitHub">The code is at github</a>. 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&#8217;ll be of us to somebody besides me.</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2009/02/hacking-wordpress-to-support-per-post-banner-images/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>New home for Rails &#8216;geo plugin comparison&#8217;</title>
		<link>http://jystewart.net/process/2008/10/new-home-for-rails-geo-plugin-comparison/</link>
		<comments>http://jystewart.net/process/2008/10/new-home-for-rails-geo-plugin-comparison/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 09:40:07 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[mapping]]></category>
		<category><![CDATA[Neogeography]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/?p=503</guid>
		<description><![CDATA[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 <a href="http://jystewart.net/process/2008/10/new-home-for-rails-geo-plugin-comparison/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>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.</p>
<p>You can now find the comparison chart at: <a href="/process/resources/rails-geo-plugins/">http://jystewart.net/process/resources/rails-geo-plugins/</a></p>
<p>A few updates have been lost along the way as they were solely made on the wiki, but hopefully it&#8217;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&#8217;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.</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2008/10/new-home-for-rails-geo-plugin-comparison/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rails Geo Plugins: GeoX</title>
		<link>http://jystewart.net/process/2007/10/rails-geo-plugins-geox/</link>
		<comments>http://jystewart.net/process/2007/10/rails-geo-plugins-geox/#comments</comments>
		<pubDate>Tue, 16 Oct 2007 14:26:13 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Commentary]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[geoX]]></category>
		<category><![CDATA[Neogeography]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/2007/10/rails-geo-plugins-geox/</guid>
		<description><![CDATA[GeoX is the latest kid on the Ruby on Rails geocoding block. The plugin was announced a couple of weeks ago and I&#8217;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 <a href="http://jystewart.net/process/2007/10/rails-geo-plugins-geox/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.misuse.org/science/2007/09/25/geox-rails-geocoding-plugin/">GeoX</a> is the latest kid on the Ruby on Rails geocoding block. The plugin was announced a couple of weeks ago and I&#8217;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 <a href="http://foss4r.dyndns.org/trac/wiki/ComparingRailsGeoPlugins">my comparison chart</a>.</p>
<p>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&#8217;s relatively recent API. The standard lookup process is much like that provided by several other plugins&#8212;the sample given is:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'geox'</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># uses the google engine</span>
geocoder = <span style="color:#6666ff; font-weight:bold;">GeoX::Geocoder</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:geoengine</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#6666ff; font-weight:bold;">GeoX::Google</span><span style="color:#006600; font-weight:bold;">&#41;</span> 
location = <span style="color:#006600; font-weight:bold;">&#123;</span>:address <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'701 Ocean St'</span>, <span style="color:#ff3333; font-weight:bold;">:post_code</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'95060'</span><span style="color:#006600; font-weight:bold;">&#125;</span>
geocode = geocoder.<span style="color:#9900CC;">geocode</span><span style="color:#006600; font-weight:bold;">&#40;</span>location<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># geocode will be a hash containing the geocode data returned from the server</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> geocode.<span style="color:#9900CC;">inspect</span></pre></div></div>

<p>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 <em>blank?</em> 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.</p>
<p>Probably the most intriguing aspect of the plugin is the facility to compare the specificity of two different sets of coordinates. That&#8217;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:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Street wins!&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#6666ff; font-weight:bold;">GeoX::Street</span>.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">GeoX::Block</span>.<span style="color:#9900CC;">new</span></pre></div></div>

<p>The README file suggests putting the API keys in the file lib/geox_api_keys.rb within the plugin. That&#8217;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.</p>
<p>I can&#8217;t see myself switching to GeoX from the options I currently use and it&#8217;s a shame that its distinctive features weren&#8217;t submitted as patches to existing projects rather than adding yet another plugin to the increasingly crowded scene, but it&#8217;ll be interesting to see how it evolves over the coming months.</pre>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2007/10/rails-geo-plugins-geox/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Rails Geo Plugins: GeoKit</title>
		<link>http://jystewart.net/process/2007/03/rails-geo-plugins-geokit/</link>
		<comments>http://jystewart.net/process/2007/03/rails-geo-plugins-geokit/#comments</comments>
		<pubDate>Mon, 12 Mar 2007 17:52:59 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Notes]]></category>
		<category><![CDATA[acts_as_geocodable]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[Geography]]></category>
		<category><![CDATA[GeoKit]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/2007/03/rails-geo-plugins-geokit/</guid>
		<description><![CDATA[There&#8217;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&#8217;t, so I decided to give it a whirl.
Since my main geographically related projects are both now based on plugins that I&#8217;m pretty happy with <a href="http://jystewart.net/process/2007/03/rails-geo-plugins-geokit/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s quite a bit of overlap between <a href="http://geokit.rubyforge.org/">GeoKit</a> and <a href="/process/2007/03/rails-geo-plugins-acts_as_geocodable/">acts_as_geocodable/graticule</a>, as the latter pair were based on GeoKit. But it provides at least one feature (IP-based location lookup) that they don&#8217;t, so I decided to give it a whirl.</p>
<p>Since my main geographically related projects are both now based on plugins that I&#8217;m pretty happy with and which suit them well, I decided to resuscitate an old sample piece.  A few months back <a href="/2006/09/scraping-grand-rapids-bus-routes/">I wrote about scraping the Grand Rapids bus routes site</a> and put up a toy application utilising the resource features in then-edge Rails. I&#8217;ve been meaning to return to that project to test out some features in <a href="http://svn.rubyonrails.org/rails/trunk/activeresource/">ActiveResource</a>, but in the meantime it seemed like it might be useful to be able to search for the nearest bus stop.</p>
<p>The plugin comes with an extensive README file and getting up and running is very straightforward:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> BusStop <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
	acts_as_mappable <span style="color:#ff3333; font-weight:bold;">:default_units</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:kms</span>, 
		<span style="color:#ff3333; font-weight:bold;">:default_formula</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:flat</span>, 
		<span style="color:#ff3333; font-weight:bold;">:distance_field_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:distance</span>,
		<span style="color:#ff3333; font-weight:bold;">:lng_column_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'longitude'</span>, <span style="color:#ff3333; font-weight:bold;">:lat_column_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'latitude'</span></pre></div></div>

<p>I had to add the column_name parameters to signify which database columns I was using, as the plugin defaults to using &#8216;lat&#8217; and &#8216;lng&#8217; 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.</p>
<p>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 <a href="http://grwifi.net/location/view/common-ground">Common Ground Coffee Shop</a> I could call:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">BusStop.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:nearest</span>, 
	<span style="color:#ff3333; font-weight:bold;">:origin</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'1319 Fulton St. East, Grand Rapids MI 49503'</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>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.</p>
<p>Where it seemed to fall over was when I tried to limit by bus route:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">BusStop.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:nearest</span>, <span style="color:#ff3333; font-weight:bold;">:origin</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'1319 Fulton St. East, Grand Rapids MI 49503'</span>,
	<span style="color:#ff3333; font-weight:bold;">:include</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:route_stops</span>, 
	<span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'route_stops.bus_route_id = 6'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
<span style="color:#6666ff; font-weight:bold;">ActiveRecord::StatementInvalid</span>: <span style="color:#6666ff; font-weight:bold;">Mysql::Error</span>: Unknown column <span style="color:#996600;">'distance'</span> <span style="color:#9966CC; font-weight:bold;">in</span> <span style="color:#996600;">'field list'</span>: <span style="color:#CC0066; font-weight:bold;">SELECT</span> DISTINCT bus_stops.<span style="color:#9900CC;">id</span>, distance FROM bus_stops  LEFT OUTER JOIN route_stops ON route_stops.<span style="color:#9900CC;">bus_stop_id</span> = bus_stops.<span style="color:#9900CC;">id</span> WHERE <span style="color:#006600; font-weight:bold;">&#40;</span>route_stops.<span style="color:#9900CC;">bus_route_id</span> = <span style="color:#006666;">6</span><span style="color:#006600; font-weight:bold;">&#41;</span> ORDER BY distance ASC  LIMIT <span style="color:#006666;">1</span></pre></div></div>

<p><a href="http://earthcode.com/">Andre Lewis</a>, one of the plugin&#8217;s developers (along with <a href="http://blog.billeisenhauer.com/">Bill Eisenhauer</a>), tells me that GeoKit doesn&#8217;t currently support the :include option or conditions on join tables. He&#8217;s hoping to add that soon, but for now you&#8217;re limited to a single table.</p>
<p>Implementing the IP-based geolocation was very easy. A before_filter is included which can be included in a controller with the declaration:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">geocode_ip_address</pre></div></div>

<p>will return a <a href="http://geokit.rubyforge.org/api/classes/GeoKit/GeoLoc.html">GeoLoc</a> 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:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> ApplicationController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActionController::Base</span>
  before_filter <span style="color:#ff3333; font-weight:bold;">:find_nearest_stop</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> find_nearest_stop
    <span style="color:#0066ff; font-weight:bold;">@nearest</span> = BusStop.<span style="color:#9900CC;">find_nearest</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:origin</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> get_ip_address<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>(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&#8217;t work as a source IP address for these purposes, and it&#8217;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&#8217;s clear, it&#8217;s a nice feature to add to local information services, potentially getting users to relevant information more quickly.</p>
<p>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&#8217;s likely that once GeoKit adds full join support, choosing between them may well come down to personal taste.</p>
<p>(Nb. Those following along with these posts may be interested in GeoKit co-author Andre Lewis&#8217; book <a href="http://www.amazon.com/exec/obidos/ASIN/1590597877/sarahmasenof-20">Beginning Google Maps Applications with Rails and Ajax</a>. I&#8217;m hoping to check it out soon)</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2007/03/rails-geo-plugins-geokit/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Extending acts_as_geocodable</title>
		<link>http://jystewart.net/process/2007/03/extending-acts_as_geocodable/</link>
		<comments>http://jystewart.net/process/2007/03/extending-acts_as_geocodable/#comments</comments>
		<pubDate>Sun, 11 Mar 2007 20:48:35 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Notes]]></category>
		<category><![CDATA[acts_as_geocodable]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[Geography]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/2007/03/extending-acts_as_geocodable/</guid>
		<description><![CDATA[After writing my review of acts_as_geocodable/graticule earlier in the week, I decided to go searching for geocoding services that might offer data for addresses outside of North America. One that I came across is at Local Search Maps. There&#8217;s an introductory blog entry here.
The API is a little different in that it returns its data <a href="http://jystewart.net/process/2007/03/extending-acts_as_geocodable/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>After writing <a href="/process/2007/03/rails-geo-plugins-acts_as_geocodable/">my review of acts_as_geocodable/graticule</a> earlier in the week, I decided to go searching for geocoding services that might offer data for addresses outside of North America. One that I came across is at <a href="http://www.localsearchmaps.com/">Local Search Maps</a>. There&#8217;s an introductory blog entry <a href="http://emad.fano.us/blog/?p=277">here</a>.</p>
<p>The API is a little different in that it returns its data as javascript strings, but otherwise it&#8217;s simple enough to send a GET for a given address and get back the data. To see how easy it is, I decided to code up an extra geocoder for graticule that would use this service.</p>
<p>The main change I had to make was to allow for extra arguments to the locate method. For the geocoders distributed with the gem there&#8217;s just one argument: the address. For this service to retrieve data outside the USA it requires more structured data, so I added an optional argument for the locate method and built my query based on its existence. The code turned out to be very simple:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'graticule'</span>
<span style="color:#9966CC; font-weight:bold;">module</span> Graticule
&nbsp;
  <span style="color:#008000; font-style:italic;"># A library for lookup of coordinates with http://geo.localsearchmaps.com/</span>
  <span style="color:#9966CC; font-weight:bold;">class</span> LocalSearchMapsGeocoder <span style="color:#006600; font-weight:bold;">&lt;</span> RestGeocoder
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize
      <span style="color:#0066ff; font-weight:bold;">@url</span> = <span style="color:#CC00FF; font-weight:bold;">URI</span>.<span style="color:#9900CC;">parse</span> <span style="color:#996600;">'http://geo.localsearchmaps.com/'</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># This web service will handle some addresses outside the US</span>
    <span style="color:#008000; font-style:italic;"># if given more structured arguments than just a string address</span>
    <span style="color:#008000; font-style:italic;"># So allow input as a hash for the different arguments (:city, :country, :zip)</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> locate<span style="color:#006600; font-weight:bold;">&#40;</span>address, args = <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> args.<span style="color:#9900CC;">empty</span>?
        get <span style="color:#ff3333; font-weight:bold;">:address</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> address
      <span style="color:#9966CC; font-weight:bold;">else</span>
        get args.<span style="color:#9900CC;">merge</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:street</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> address<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> check_error<span style="color:#006600; font-weight:bold;">&#40;</span>js<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#CC0066; font-weight:bold;">raise</span> AddressError, <span style="color:#996600;">&quot;Empty Response&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> js.<span style="color:#0000FF; font-weight:bold;">nil</span>? <span style="color:#9966CC; font-weight:bold;">or</span> js.<span style="color:#9900CC;">text</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?
      <span style="color:#CC0066; font-weight:bold;">raise</span> AddressError, js.<span style="color:#9900CC;">text</span>.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>alert\<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'(.+)'</span>\<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">if</span> js.<span style="color:#9900CC;">text</span> == <span style="color:#996600;">&quot;alert('location not found');&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> parse_response<span style="color:#006600; font-weight:bold;">&#40;</span>js<span style="color:#006600; font-weight:bold;">&#41;</span>
      location = Location.<span style="color:#9900CC;">new</span>
      coords = js.<span style="color:#9900CC;">text</span>.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>map.<span style="color:#9900CC;">centerAndZoom</span>\<span style="color:#006600; font-weight:bold;">&#40;</span>new GPoint\<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#40;</span>.<span style="color:#006600; font-weight:bold;">+</span>?<span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#006600; font-weight:bold;">&#40;</span>.<span style="color:#006600; font-weight:bold;">+</span>?<span style="color:#006600; font-weight:bold;">&#41;</span>\<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      location.<span style="color:#9900CC;">longitude</span> = coords<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      location.<span style="color:#9900CC;">latitude</span> = coords<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      location
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>So now I can use graticule and specify an address such as:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">g = <span style="color:#6666ff; font-weight:bold;">Graticule::LocalSearchMapsGeocoder</span>.<span style="color:#9900CC;">new</span>
location = g.<span style="color:#9900CC;">locate</span> <span style="color:#996600;">'14, Avenue Claude Vellefaux'</span>, 
	<span style="color:#ff3333; font-weight:bold;">:zip</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'75010'</span>, <span style="color:#ff3333; font-weight:bold;">:city</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Paris'</span>, <span style="color:#ff3333; font-weight:bold;">:country</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'France'</span></pre></div></div>

<p>and find out that that address is at latitude 48.873016, longitude 2.369934. Unfortunately it is still quite a limited service; when I threw in some addresses in China, Malaysia and even New Zealand I got Graticule::AddressError exceptions. But such is the current state of geocoding, and getting some of Western Europe on top of North America is progress.</p>
<p>Another extension for graticule that might be nice would be a way to specify countries that a geocoder does/doesn&#8217;t support. That way the gem could intelligently choose a geocoder that will work out for the specified address.</p>
<p><strong>Update (March 21st): This code is now included in the latest release of the graticule gem.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2007/03/extending-acts_as_geocodable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails Geo Plugins: acts_as_geocodable</title>
		<link>http://jystewart.net/process/2007/03/rails-geo-plugins-acts_as_geocodable/</link>
		<comments>http://jystewart.net/process/2007/03/rails-geo-plugins-acts_as_geocodable/#comments</comments>
		<pubDate>Wed, 07 Mar 2007 19:53:05 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Notes]]></category>
		<category><![CDATA[acts_as_geocodable]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[Geography]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/2007/03/rails-geo-plugins-acts_as_geocodable/</guid>
		<description><![CDATA[acts_as_geocodable (blog entry, repository) is the newest kid on the rails geo plugin block. It actually consists of two parts, a gem called graticule which handles the actual geocoding, interacting with external services, etc, and the plugin which offers extensions to your models.
I like that separation. Having the generalised code in a gem and the <a href="http://jystewart.net/process/2007/03/rails-geo-plugins-acts_as_geocodable/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>acts_as_geocodable (<a href="http://opensoul.org/2007/2/13/geocoding-as-easy-as-1-2">blog entry</a>, <a href="http://source.collectiveidea.com/public/rails/plugins/acts_as_geocodable/README">repository</a>) is the newest kid on the rails geo plugin block. It actually consists of two parts, a gem called <a href="http://rubyforge.org/projects/graticule/">graticule</a> which handles the actual geocoding, interacting with external services, etc, and the plugin which offers extensions to your models.</p>
<p>I like that separation. Having the generalised code in a gem and the rails-specific hooks in a plugin makes a lot of sense and makes it much easier to use the core code in non-rails ruby apps, and having a single gem that supports multiple services allows for built-in failover should the preferred geocoder be unavailable.</p>
<p>Much of the functionality of the plugin is already integrated into my application, but not with quite so many options. In such cases I really enjoy installing plugins; there&#8217;s something very satisfying about going through my application deleting code. </p>
<p>The plugin adds two tables to your database. The first, geocodes, holds longitudes/latitudes for given addresses, while the other, geocodings, polymorphically links those geocodes to your existing models. In my case, this meant re-geocoding all the locations already in my database, but since I&#8217;m operating on a fairly small data set, that was a pretty simple case of iterating across them all and re-saving them. For those operating with very large databases, you may want to write a more sophisticated migration to handle that.</p>
<p>The trickiest thing was re-coding my search queries to use the new database. acts_as_geocodable offers a number of neat methods for running queries such as (from their documentation)</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  event.<span style="color:#9900CC;">distance_to</span> <span style="color:#996600;">&quot;49423&quot;</span>
&nbsp;
  Event.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:within</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">50</span>, <span style="color:#ff3333; font-weight:bold;">:origin</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;97232&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  Event.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:nearest</span>, <span style="color:#ff3333; font-weight:bold;">:origin</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Portland, OR&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>But I wanted a way to build more sophisticated searches so I could, say, limit by title and order by distance. It turns out that&#8217;s pretty easy too:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Location.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:origin</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Grand Rapids MI'</span>, 
	<span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'title LIKE ?'</span>, <span style="color:#996600;">'My Title'</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#ff3333; font-weight:bold;">:order</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'distance'</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>The one place where I had a problem was when trying to use the last of the examples.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Location.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:nearest</span>, <span style="color:#ff3333; font-weight:bold;">:origin</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Portland, OR'</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>blew up with:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::StatementInvalid</span>: <span style="color:#6666ff; font-weight:bold;">Mysql::Error</span>: Incorrect parameter count <span style="color:#9966CC; font-weight:bold;">in</span> the call to native function <span style="color:#996600;">'RADIANS'</span>: <span style="color:#CC0066; font-weight:bold;">SELECT</span> locations.<span style="color:#006600; font-weight:bold;">*</span>, geocodes.<span style="color:#006600; font-weight:bold;">*</span>,
            <span style="color:#006600; font-weight:bold;">&#40;</span>ACOS<span style="color:#006600; font-weight:bold;">&#40;</span> SIN<span style="color:#006600; font-weight:bold;">&#40;</span>RADIANS<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">*</span> SIN<span style="color:#006600; font-weight:bold;">&#40;</span>RADIANS<span style="color:#006600; font-weight:bold;">&#40;</span>geocodes.<span style="color:#9900CC;">latitude</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">+</span> COS<span style="color:#006600; font-weight:bold;">&#40;</span>RADIANS<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">*</span> COS<span style="color:#006600; font-weight:bold;">&#40;</span>RADIANS<span style="color:#006600; font-weight:bold;">&#40;</span>geocodes.<span style="color:#9900CC;">latitude</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">*</span> COS<span style="color:#006600; font-weight:bold;">&#40;</span>RADIANS<span style="color:#006600; font-weight:bold;">&#40;</span>geocodes.<span style="color:#9900CC;">longitude</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">-</span> RADIANS<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">*</span> <span style="color:#006666;">3963.1676</span><span style="color:#006600; font-weight:bold;">&#41;</span>  AS
            distance FROM locations  JOIN geocodings ON
              locations.<span style="color:#9900CC;">id</span> = geocodings.<span style="color:#9900CC;">geocodable_id</span> <span style="color:#9966CC; font-weight:bold;">AND</span>
                geocodings.<span style="color:#9900CC;">geocodable_type</span> = <span style="color:#996600;">'Location'</span>
              JOIN geocodes ON geocodings.<span style="color:#9900CC;">geocode_id</span> = geocodes.<span style="color:#9900CC;">id</span>  ORDER BY distance ASC LIMIT <span style="color:#006666;">1</span></pre></div></div>

<p>but when I used a full address (my home) in the same query, I got an appropriate result. It looks as though perhaps if it fails to get an appropriate pair of co-ordinates for the specified location, it tries to perform the query anyway, with an exception resulting.</p>
<p>I also found some problems when trying to use the plugin with locations outside North America, but that is a limitation of the geocoding services and not of the gem or plugin themselves. Hasten the day when enough data is open that global geocoding services can become a reality.</p>
<p>Working with acts_as_geocodable has so far been a very straightforward experience and has allowed me to rid my code of some pieces I&#8217;d always meant to refactor out. It&#8217;d be good to see the error I ran into handled more neatly, and perhaps an obvious API to take advantage of the failover options presented by graticule, but the plugin is still early in its life and shows a lot of promise.</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2007/03/rails-geo-plugins-acts_as_geocodable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ActiveMerchant</title>
		<link>http://jystewart.net/process/2007/02/activemerchant/</link>
		<comments>http://jystewart.net/process/2007/02/activemerchant/#comments</comments>
		<pubDate>Thu, 22 Feb 2007 21:02:06 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Notes]]></category>
		<category><![CDATA[activemerchant]]></category>
		<category><![CDATA[credit card processing]]></category>
		<category><![CDATA[payment gateway]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/archives/2007/02/activemerchant/</guid>
		<description><![CDATA[By far the most popular (and most versatile) plugin for working with payment gateways from rails is ActiveMerchant. I&#8217;ve used it in a couple of places, and it&#8217;s been a joy to work with, apart from one slip-up which was largely due to inadequate documentation. So I&#8217;m very pleased to note that they&#8217;ve release their <a href="http://jystewart.net/process/2007/02/activemerchant/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>By far the most popular (and most versatile) plugin for working with payment gateways from rails is ActiveMerchant. I&#8217;ve used it in a couple of places, and it&#8217;s been a joy to work with, apart from one slip-up which was largely due to inadequate documentation. So I&#8217;m very pleased to note that they&#8217;ve release their 1.0 and launched <a href="http://www.activemerchant.org/">a website</a>, which bodes well for improved documentation and support.</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2007/02/activemerchant/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>model_auto_completer</title>
		<link>http://jystewart.net/process/2007/02/model_auto_completer/</link>
		<comments>http://jystewart.net/process/2007/02/model_auto_completer/#comments</comments>
		<pubDate>Mon, 19 Feb 2007 13:23:25 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Notes]]></category>
		<category><![CDATA[auto completion]]></category>
		<category><![CDATA[helpers]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/archives/2007/02/model_auto_completer/</guid>
		<description><![CDATA[Rails&#8217; auto_complete integration is pretty nice for building search functionality, but for entry forms it all too often falls short.
Typically if I&#8217;m using an auto complete field in a form it&#8217;s because I want to link that record with an existing entry in another table, such as connecting an event with a location, or a <a href="http://jystewart.net/process/2007/02/model_auto_completer/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>Rails&#8217; <a href="http://rails.rubyonrails.org/classes/ActionView/Helpers/JavaScriptMacrosHelper.html">auto_complete</a> integration is pretty nice for building search functionality, but for entry forms it all too often falls short.</p>
<p>Typically if I&#8217;m using an auto complete field in a form it&#8217;s because I want to link that record with an existing entry in another table, such as connecting an event with a location, or a book with a publisher, and that won&#8217;t work because the value obtained from the auto completion is the name of the linked entity, not its ID. I&#8217;ve tried various ways of managing that, either by overriding the standard methods or by adding some extra code in my model that will convert a name back into the associated model ID, but they all feel like hacks and I&#8217;d not had time to clean up the code and package anything as a plugin.</p>
<p>Thankfully <a href="http://advogato.org/person/fxn/diary.html">Xavier Nora</a>&#8217;s already done it with the <a href="http://model-ac.rubyforge.org/">model_auto_completer</a> plugin. The plugin provides a set of helper methods that will allow you to use auto completion, but have the ID of the record found stored as a hidden field in your form, making processing considerably easier.</p>
<p>Initially I had a problem using the plugin, and in fact found my rails application falling over because the plugin wasn&#8217;t getting the right name for the foreign key and since I have other fields that allow entry of a new location, rails couldn&#8217;t tell if a post with:</p>
<p>location[]=123&#038;location[name]=My%20Location</p>
<p>should use the first location data or the later data.</p>
<p>Looking through the code I found that instead of using:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">foreign_key  = real_object.<span style="color:#9966CC; font-weight:bold;">class</span>.<span style="color:#9900CC;">reflect_on_association</span><span style="color:#006600; font-weight:bold;">&#40;</span>association<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">options</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:foreign_key</span><span style="color:#006600; font-weight:bold;">&#93;</span></pre></div></div>

<p>to get the foreign key it should be using:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">foreign_key = real_object.<span style="color:#9966CC; font-weight:bold;">class</span>.<span style="color:#9900CC;">reflect_on_association</span><span style="color:#006600; font-weight:bold;">&#40;</span>association<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">primary_key_name</span></pre></div></div>

<p>Having submitted a patch, I was very pleased to hear over the weekend that the change has been integrated into the plugin so I can let piston update back to the official trunk. With that change in place, the plugin is a great way to make data entry much more convenient.</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2007/02/model_auto_completer/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>loads_from_amazon (Ruby on Rails plugin)</title>
		<link>http://jystewart.net/process/2006/07/loads_from_amazon-ruby-on-rails-plugin/</link>
		<comments>http://jystewart.net/process/2006/07/loads_from_amazon-ruby-on-rails-plugin/#comments</comments>
		<pubDate>Thu, 20 Jul 2006 18:59:57 +0000</pubDate>
		<dc:creator>James Stewart</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[amazon ecommerce services]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://jystewart.net/process/archives/2006/07/loads_from_amazon-ruby-on-rails-plugin/</guid>
		<description><![CDATA[UPDATE (10/2008): This plugin is no longer maintained. I&#8217;d recommend looking at one of the newer alternatives such as acts_as_amazon_product if you need this functionality.

I&#8217;ve been procrastinating on getting my first Ruby on Rails plugin (first anyone else might be interested in, at least) out the door, mainly due to some configuration problems with Subversion, <a href="http://jystewart.net/process/2006/07/loads_from_amazon-ruby-on-rails-plugin/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE (10/2008)</strong>: This plugin is no longer maintained. I&#8217;d recommend looking at one of the newer alternatives such as <a href="http://github.com/netphase/aaap/tree/master">acts_as_amazon_product</a> if you need this functionality.</p>
<hr />
<p>I&#8217;ve been procrastinating on getting my first Ruby on Rails plugin (first anyone else might be interested in, at least) out the door, mainly due to some configuration problems with Subversion, but finally I have that all sorted out and the plugin ready to go.</p>
<p><a href="http://projects.jystewart.net/svn/rails/loads_from_amazon/trunk">loads_from_amazon</a> is an ActiveRecord Mixin that works with the <a href="http://www.caliban.org/ruby/ruby-amazon.shtml">Ruby/Amazon</a> library to let you populate an ActiveRecord object with the details of a product listed on amazon. In the README I use the following example:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Book <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  acts_as_amazon
  maps_to_amazon_attribute <span style="color:#ff3333; font-weight:bold;">:authorlist</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'authors'</span>, <span style="color:#ff3333; font-weight:bold;">:combine</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">';'</span>
  maps_to_amazon_attribute <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'product_name'</span>
  maps_to_amazon_attribute <span style="color:#ff3333; font-weight:bold;">:isbn</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'asin'</span>
  maps_to_amazon_attribute <span style="color:#ff3333; font-weight:bold;">:publisher</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'manufacturer'</span>
  maps_to_amazon_attribute <span style="color:#ff3333; font-weight:bold;">:pubdate</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'release_date'</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#0066ff; font-weight:bold;">@book</span> = Book.<span style="color:#9900CC;">load_from_amazon</span><span style="color:#006600; font-weight:bold;">&#40;</span>isbn<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;"># Loads but does not save</span>
<span style="color:#0066ff; font-weight:bold;">@otherbook</span> = Book.<span style="color:#9900CC;">load_from_amazon</span>!<span style="color:#006600; font-weight:bold;">&#40;</span>other_isbn<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;"># Loads data and saves to database</span></pre></div></div>

<p>So feel free to grab it from svn (<a href="http://projects.jystewart.net/svn/rails/loads_from_amazon/trunk">http://projects.jystewart.net/svn/rails/loads_from_amazon/trunk</a>) and let me know what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://jystewart.net/process/2006/07/loads_from_amazon-ruby-on-rails-plugin/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>
