Oliver Legg

Google's OpenSocial with Ruby on Rails


Given the fair number of web applications we have developed with some aspect of social networking involved, naturally we were pretty excited about Google's OpenSocial announcement.

Looking into the OpenSocial documentation you can see that it exposes 3 different types of resources: people, that person's friends, and their activities. This structure maps nicely onto Rail's concept of nested resources, where we could have a top-level users controller with friends and activities nested underneath it.

The OpenSocial API looks quite well thought out, and built upon RESTful ideas. However it doesn't fit completely with the Rails ideals. Firstly the URL's for accessing the resources aren't the standard Rails routes and secondly it doesn't include a format extension, which means we can't use a responds_to block out of the box.

However both of these problems are easily solved by adding a few mappings to the routes file and adding our own custom mimetype. The example below shows the routing for mapping the users controller to the OpenSocial people resource.

# config/environment.rb
Mime::Type.register "application/x-opensocial", :opensocial

# config/routes.rb
map.opensocial_person '/feeds/people/:id', :controller => 'users', \
                            :action => 'show', :format => 'opensocial',\
                            :conditions => {:method => :get}

map.opensocial_person '/feeds/people/:id', :controller => 'users',\
                            :action => 'update', :format => 'opensocial', \
                            :conditions => {:method => :put}

map.opensocial_person '/feeds/people/:id', :controller => 'users', \
                             :action => 'destroy', :format => 'opensocial', \
                             :conditions => {:method => :delete}

# app/controllers/users_controller.rb

respond_to do |format|

Now you can render show.opensocial.erb or show.opensocial.builder to create atom feeds that the OpenSocial API requires.

To avoid repeating it throughout a number of applications I wrapped it up into a little plugin that just sets the routes for those three resources, like so.

# config/routes.rb
map.resources :users do |user|
  user.resources :activities
  user.resources :relationships

map.opensocial_people :users do |user|
  user.opensocial_friends :relationships
  user.opensocial_activities :activities

Download Plugin