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!