Positive Incline Mike Burrows (@asplake) moving on up, positively

July 27, 2009

Putting it all together – ResourceTemplates, described_routes and path-to

Filed under: Web Integration — Tags: , , , — Mike @ 10:18 pm

We’ve watched described_routes and path-to grow here over the past few weeks. And fun though it has been for me, it must be hard to get a good overview from blog posts triggered by design challenges! So here goes: an attempt at a one-post overview.

In a sentence?

Add described_routes to your Rails application to give it header-based site discovery with ResourceTemplate metadata that enables instant Ruby APIs on the client side with path-to.

And if I’m not using Rails or even Ruby?

There’s library support for ResourceTemplate metadata in Ruby (for the moment it’s included as part of described_routes) and Python (see described_routes-py). There’s a simpler version of path-to available in Python also, namely path-to-py. And there’s nothing Rails-specific or complicated about ResourceTemplates either – strip away the JSON, YAML or XML formatting and they’re not much more than named resources arranged hierarchically with their URI templates and supported HTTP methods as properties – and (so I’m told) can be useful even without path-to.

OK – I’m sold! What do I have to do?

Just follow these simple steps:

  1. Install described_routes for the server
  2. Add build-time integration to the server
  3. Add basic run-time integration to the server
  4. Add site discovery to the server
  5. Install and run path-to
  6. Profit!

The README files of the two gems tell you all you need to know in detail, but here in one place:

1. Install described_routes for the server

$ sudo gem install described_routes

2. Add build-time integration to the server

This is just a set of Rake tasks that lets you see immediately what the metadata looks like. In your Rakefile:

require 'tasks/described_routes'

Then try it out:

$ rake --tasks described_routes
rake described_routes:json        # Describe resource structure in JSON format
rake described_routes:xml         # Describe resource structure in XML format
rake described_routes:yaml        # Describe resource structure in YAML format
rake described_routes:text        # Describe resource structure in text (comparable to "rake routes")

Specify the base URI of your app with "BASE=http://..." to see full URIs in the output.

3. Add basic run-time integration to the server

Somewhere in your application include the controller, perhaps in an initializer:

require 'described_routes/rails_controller'

Add the following route in config/routes.rb:

map.resources :described_routes, :controller => "described_routes/rails"

You can now browse to /described_routes(.format) and /described_routes/{controller_name}(.format) and see the data generated at run time.

4. Add site discovery to the server

Site discovery (linking resources to their resource-specific and site-wide metadata) works via link headers (“Link:“) added to the responses served by one or more controllers. This has a double benefit:

i) Resources gain some type information derived from the Rails route name of the resource that may be of value to clients
ii) A path-to client (or any other client interested in the ResourceTemplate metadata) can be initialised from a regular resource URI; prior knowledge of metadata location is not needed.

According to your requirements, add the set_link_header filter to either the controller of your root resource (&/or or other specific controllers) or to ApplicationController in order to benefit all controllers:

require 'described_routes/helpers/described_routes_helper'

class MyController < ApplicationController
  include DescribedRoutes::DescribedRoutesHelper
  after_filter :set_link_header

Install and run path-to, …profit!

$ sudo gem install path-to

It is now a one-liner to bootstrap a client application, in this example a test blog with user and article resources:

require "path-to/described_routes"

# bootstrap a path-to client from the test_rails_app provided in described_routes
app = PathTo::DescribedRoutes::Application.discover("http://localhost:3000/")
#=> <PathTo::DescribedRoutes::Application>

# get user 'dojo'
puts app.users['dojo'].get
#=> '<html>...</html>

#get a JSON representation of the recent articles of user 'dojo'
puts app.users['dojo'].articles.recent['format' => 'json'].get
#=> [...]


This bit is up to you, but metadata-enhanced web apps and instant client APIs achieved for so little work has to be worth something!

1 Comment

  1. […] Putting it all together – ResourceTemplates, described_routes and path-to – Plumbing to handle header-based discovery and easier client APIs. […]

    Pingback by Double Shot #505 « A Fresh Cup — July 28, 2009 @ 11:07 am

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress