Model web apps easily and access them via nice app-specific Ruby APIs.
Note to reader: You are invited to comment on the roadmap at positiveincline.com/?p=213
path-to allows web applications to be modelled via URI templates and then accessed through an application-specific Ruby API. It is designed to be extended easily to support discovery mechanisms; included is an implementation based on the resource templates of described_routes.
Create a client application configured from a server that supports described_routes:
require 'path-to/described_routes' app = PathTo::DescribedRoutes::Application.new(:json => Net::HTTP.get(URI.parse("http://example.com/described_routes.json"))) app.users["dojo"].articles.recent #=> http://example.com/users/dojo/articles/recent app.users["dojo"].articles.recent.get #=> "<html>...</html>" app.users["dojo"].articles.recent["format" => "json"] #=> http://example.com/users/dojo/articles/recent.json app.users["dojo"].articles.recent.get #=> [...]
See examples/delicious.rb for an example based on a partial YAML-based description of the Delicious API.
require "path-to" class Users < PathTo::Path ; end class Articles < PathTo::Path ; end app = Application.new( :users => "http://example.com/users/{user}", :articles => "http://example.com/users/{user}/articles/{slug}") do |app| def app.child_class_for(instance, method, params) { :users => Users, :articles => Articles }[method] end end #=> Application
Note that the Users and Articles classes and the overridden #child_class_for method above can be done away with (reducing the above code to just four lines) if there is no need to define any class-specific behaviour.
Having defined URI template and class mappings for keys :users and :articles mapping to URI templates, calls to app.users and app.articles cause objects of the appropriate class to be generated. These in turn support chaining and the collection of request params, like this:
app.users #=> http://example.com/users/ <Users> app.users(:user => "dojo") #=> http://example.com/users/dojo <Users> app.users[:user => "dojo"] #=> http://example.com/users/dojo <Users> app.articles(:user => "dojo", :slug => "my-article") #=> http://example.com/users/dojo/articles/my-article <Articles> app.users[:user => "dojo"].articles[:slug => "my-article"] #=> http://example.com/users/dojo/articles/my-article <Articles>
With a little more work (overriding Users#[] and Articles#[] - as described in the documentation for the Path class), the last example becomes simply:
app.users["dojo"].articles["my-article"] #=> http://example.com/users/dojo/articles/my-article <Articles>
HTTP support comes courtesy of HTTParty (the Path class includes it). To GET an article in the above example, just invoke the get method on the path object:
app.users["dojo"].articles["my-article"].get #=> "<html>...</html>"
sudo gem install path-to
Mike Burrows (asplake), email mjb@asplake.co.uk, website positiveincline.com (articles tagged path-to)