Latest gems, URI Template update

Bob Aman (sporkmonger) has released the latest version of the excellent addressable to RubyForge so that it’s no longer necessary to get it from github.  This incorporates amongst other things (my minor bug fixes included) Bob’s cool new partial URI Template expansion feature that is the foundation of the changes described in my previous post.  I’ve updated both described_routes and path-to so that installing either of these will pull in addressable automatically.

So:

$ sudo gem install described_routes path-to
Successfully installed addressable-2.1.0
Successfully installed described_routes-0.4.1
Successfully installed path-to-0.4.1
3 gems installed

and you’re done.

Meanwhile, the uri@w3.org list awoke this week in response to a request from Joe Gregorio for examples of real-world usage of URI Templates and feedback on whether simplification was warranted.  Bob and I were united in asking that the advance features not be withdrawn – they are genuinely useful!

Nested path-to/described_routes and HTTParty

I’ve finished the support for nested described_routes in path-to.  Example:

  require 'path-to/described_routes'
  app = PathTo::DescribedRoutes::Application.new(
      :json => Net::HTTP.get(URI.parse("http://example.com/described_routes.json")))

  app.users["user_id" => "dojo"].articles.recent
  #=> http://example.com/users/dojo/articles/recent
  app.users["user_id" => "dojo"].articles.recent.get
  #=> "<html>...</html>"

Or if you still prefer the named route:

  app.recent_user_articles("user_id" => "dojo").get   #=> "<html>...</html>"

And that’s it!  Is that a client-side API for free or what?  This just has to be better than hard-coded URIs (ugh).

I have also enhanced the Rails controller in described_routes so that you can get the JSON, YAML or XML for a given named route.  In this example we see HTTParty (path-to’s default HTTP client) parsing a JSON response (which I’ve reformatted just a little bit):

  app.described_route("route_name" => "admin_product", "format" => "json").get
  #=> {"name"=>"admin_product", "options"=>["GET", "PUT", "DELETE"],
       "resource_templates"=>[
          {"name"=>"edit_admin_product", "options"=>["GET"],
           "uri_template"=>"http://localhost:3000/admin/products/{product_id}/edit{-prefix|.|format}",
           "path_template"=>"/admin/products/{product_id}/edit{-prefix|.|format}", "rel"=>"edit",
           "optional_params"=>["format"], "params"=>["product_id"]
          }],
       "uri_template"=>"http://localhost:3000/admin/products/{product_id}{-prefix|.|format}",
       "path_template"=>"/admin/products/{product_id}{-prefix|.|format}",
       "optional_params"=>["format"], "params"=>["product_id"]}

One last thing: as previously mentioned you’ll need grab the latest addressable from github – the published gem is a fix or two behind.

path-to is born: nice client-side APIs to web applications in Ruby

An initial cut of path-to is now on github.  There’s no gem on Rubyforge just yet but it’s not far away.

Path-to’s basic premise is that it should be easy to describe client interfaces to typical web applications (RESTful ones especially), and have created for you a Ruby API, even in the absence of a discoverable representation of the web API on the server side. My longer term aim is to identify convenient discovery protocols, have them implemented in the server apps I have influence over, and (naturally) include support for them in path-to.

A very simple example (expanded in the README) looks like this:

    require "path-to"

    app = Application.new(
            :users    => "http://example.com/users/{user}",
            :articles => "http://example.com/users/{user}/articles/{slug}")

    app.users                                                   #=> http://example.com/users/
    app.users(:user => "dojo")                                  #=> http://example.com/users/dojo
    app.users[:user => "dojo"]                                  #=> http://example.com/users/dojo
    app.articles(:user => "dojo", :slug => "my-article")        #=> http://example.com/users/dojo/articles/my-article
    app.users[:user => "dojo"].articles[:slug => "my-article"]  #=> http://example.com/users/dojo/articles/my-article

A key theme of path-to is chaining, so that if app.x represents a resource, then so (typically) do app.x.y and app.x[params]. But you’re not forced into this style: you could go straight for app.x(params) which involves one less object under the covers. Furthermore, you have control over the classes of the objects created, and are free to override #[] so that you can (for example) have calls like

    app.users["dojo"].articles["my-article"]                    #=> http://example.com/users/dojo/articles/my-article

Another important theme is that client applications shouldn’t be forced to follow my preferences and dependencies. For example, I’m testing it with HTTParty (so that app.x.get is delegated to HTTParty.get), but you don’t have to. Similarly, it’s easy to swap out the URI Template support I’m getting from Addressable – which is just as well, as I’m entertaining serious second thoughts about the whole URI Templates thing!

URI templates in Ruby, discovery concerns, looking at XRD

We’ve been adding RESTful interfaces to an existing distributed app to give it some much-needed scriptability.  I was able to cook up a client very easily in Ruby, using URI templates to describe the server API.  This approach got us up and running nice and quickly and I was happy enough with it, but I would have been happier still if it didn’t feel so, well, homebrewed.

Among my readings on REST and answering some of my concerns over our app’s discoverability, this very interesting post from Dare Obasanjo on REST API Design pointed me to the XRD initiative.  It’s covered in multiple posts on the excellent Hueniverse, of which this XRD Sneak-Peek is a good place to start.

XRD seems to have everything I’m looking for in a standardised web API description but for this one issue: given multiple templates that map to resources of the same type, how do I choose the the one most appropriate to the the set of parameters I have in my client?  For example, my blog might support two:

  http://positiveincline.com/articles/{slug}

http://positiveincline.com?p={id}

Having the server prioritise these (as provided for in XRD) makes no sense in this instance; the client needs to be able to choose.  How about then have some way of marking template variables as mandatory, like {+slug} perhaps?  Thoughts, anyone?

Back to Ruby meanwhile, may I recommend sporkmonger’s Addressable gem, an improved URI class with template support.  My first foray into open source contribution resulted with a minor fix to it being accepted today.  Thanks to the amazing github, this transaction was concluded in a matter of minutes!

All of this is one step along the way towards a new gem (tentatively “path-to”, registered on rubyforge) which will make it very easy to describe web applications on the client side in Ruby, and later to support discovery mechanisms such as XRD.  There are some corporate hoops to jump through before I can take this further, so watch this space.

P.S. XRD gives me hope that URI templates might still be “officially” alive, despite the expiry of the draft 3 spec.  Is there anyone out there making this so?  A lot of googling and trawling through w3c archives later and I’m still not sure.