Status
automated voice on the Utility Service phone is creepily alive
Location
1055 N Nelson St, Arlington, VA
Subscribe to GeoRSS Subscribe to KML


Programming

Rails interfaces to Mac Applications

Published in Apple, Rails


The new version of Mac OS X, Leopard, came with a much anticipated feature - an officially supported set of Ruby bridges to Cocoa (the Mac OS X Framework) and AppleScript. Digging around I couldn’t find the pre-installed versions, but it was easy enough to gem install rb-appscript

I’ve been playing around with the very complete examples over the last couple of days and am really impressed with how easy it is to build Cocoa apps in just a few lines of Ruby code and using the new InterfaceBuilder. You get full-fledged support of all OS X’s goodness without having to worry about Objective-C.

However, I hadn’t fully considered some of the implications of this until I was stumbled across the open-source OmniFocus-UI. It is a Rails app written as an iPhone interface to the Productivity application (GTD) OmniFocus. It essentially provides a very lightweight web interface to the application by way of the AppleScript interface. rb-appscript and RubyOSA are two Ruby AppleScript bridges that make AppleScript actually really nice to work with.

The fact that it’s a Rails app is almost silly. There is no database connection to speak of. All storage and primary functionality is handled by the app itself. OmniFocus-UI could probably be rewritten as a Camping or Merb application very easily with a much smaller footprint.

The way the Rails app works is that the controllers just route commands via rb-appscript. So when you want a list of contexts (organization of todos), the Rails app just needs to do the following in Ruby:

require 'appscript'
doc = Appscript.app("OmniFocus").default_document
doc.contexts.get.length

Or to see how many Inbox items you have:

doc.inbox_tasks.count

If instead you want to use RubyOSA, it’s really just the Class name that changes (and some more underlying bits):

require 'rbosa'
doc = OSA.app("OmniFocus").default_document

What this means is, it’s very easy to build web interfaces on top of any AppleScript-able Mac application. The one difficulty, however, is configuring your Mac to make it easily externally accessible from anywhere on the Web. If you’re handy on IT, you can always setup port-forwarding on your router.

However, if you just want setup & forget, you should check out Prism (http://goprism.com) - which creates secure, private web accessible connections to your home computer.


Bug in open-uri when dealing with multiple headers

Published in Programming, Ruby


I just discovered a bug in Ruby’s open-uri library, caused by the Net::HTTP library, or at best really annoying behavior that will break when you try and use it. The problem lies in dealing with an HTTP request that returns multiple values for a field. This forum topic discusses that having multiple instances of a field is valid in HTTP1.1 (RFC2616).

So when you use Net::HTTP to fetch a document like this, it will create an array for every field, holding each value found for the field. That’s great. However, in open-uri#last_modified then gets this array and joins the values together to get a single string.

The example I ran into is the Last-Modified field. Given HTTP headers like this:

HTTP/1.1 200 OK
Server: Undisclosed-Webserver/0.1
Date: Tue, 14 Aug 2007 15:03:29 GMT
Last-modified: Tue, 14 Aug 2007 15:03:29 GMT
Content-type: application/vnd.google-earth.kml+xml
Last-modified: Wed, 08 Aug 2007 18:34:55 GMT
Connection: close

And then calling response.each_header {|f,v| puts "#{f}: #{v}"} will result in Last-Modified: "Tue, 14 Aug 2007 15:21:22 GMT, Wed, 08 Aug 2007 18:34:55 GMT". Go ahead and try throwing Time.httpdate at that. You’ll get ArgumentError: not RFC 2616 compliant date:.

To simply recreate this bug, try the following ruby code:

require 'open-uri'
res = open("http://popsci.com/popsci/kml/popsci_future_environment.kml")
res.last_modified

A simple solution, or workaround, is to just get the hash and deal with it yourself: response.to_hash.each {|f,v| puts "#{f}: #{v}"} # => last-modified: "Tue, 14 Aug 2007 15:21:22 GMT

I’m not going to mention any names on this particular offending party that was silly to include 2 Last-Modified dates, but you know who you are.


TwitterVision (geo-twitter) API

Published in Geo, Programming


I haven’t gotten a chance to play with it much yet, as I’m still on travel, but Dave Troy released a simple, effective API to his TwitterVision work with geolocating twits.

The TwitterVision API looks like it was built on Rails, which means it is probably a very slick/simple addition for him to expose the data in XML, YAML, and JSON.

No sign of GeoRSS explicitly yet, so you can’t subscribe to just a feed of your friends’ locations, but that would again be something simple to add (and he does hint there is more coming), or for someone else to build on using his API.

One issue that still remains is if forcing a user to specify the “l:” prefix to a location is a usable/effective mechansism. Typing a colon (:) on a mobile phone isn’t the easiest thing to do, but at the same time using other characters such as a tilde (~) are often stripped out or munged by SMS gateways.

A more natural language parsing option would be interesting, but processing is intense with potentially very unclear results (’Sitting at the bar’, ‘Leaving home to go into town’) and also privacy or desire of the user to sometimes not share their location.

Using simple symbols, like parenths: Caffeine good (Sweetwaters Cafe)
would be a good option, since the location may not actually be part of my message, but I do want to share it.

As for parsing, something like Geocodr would provide a very robust geocoding system where the system could parse both odd areas (Soma), buildings/areas (Empire State Building), or even events (Web2.0 Expo).

So the main points are to allow opt-in based on my desire to share location (or destination), simple to enter on a mobile/laptop/brain implant, and optional location specification outside of the actual primary message content. And the issue applies outside of just Twitter, which really just serves as a good context. How would this be done in voice command for directions or location?

But again, needs to be simple and understandable. Don’t you like simple problems?


Ruby on Rails case study

Published in Rails


Allan from the NonProfitTechBlog pointed me to this article on infoQ, Ruby on Rails case study: ChangingThePresent.org.

The article does a full walk-through, from concept, through development, and to scalability, deliverability, and maintainability, of a Ruby on Rails site/service.

Discussions (arguments) between the various languages and their frameworks are common. It’s helpful to see such a readable and poignant presentation of the entire process to address the various issues other developers bring up about the platform.

I have definitely seen the same effects he talks about in the article. Development and updates occur much faster. I can be more productive creating my ideas and getting them to a working prototype. The code is easy to read and small, so its also easy to maintain the code to optimize or extend with new features.

I’m not saying that the other languages or frameworks fail at this, I know that for me, it feels like its the fastest development I can do short of natural language requirements into code (”Make me a Map” )


open-uri and can’t convert Hash into String

Published in Programming, Ruby


I’m posting this in hopes that search engines grab it and put it at the top of their list when other poor soul’s run into this problem.

If you’re trying to grab a web resource using Open-URI, and you are using basic authentication (username/password) then you’ll need to make sure to require 'open-uri' or you’ll get:

open("http://example.com/site", :http_basic_authentication => ["username", "password"])
TypeError: can't convert Hash into String

Of course, then you toss some yummy Hpricot into the mix for parsing/scraping the good bits of the HTML.