How to consume a nested singular resource?


#1

Hi,

We have a RESTful server application which exposes the following routes
using the following rules, but when trying to consume those resources
from a client application the routes are not generated correctly. And we
are not sure how to get around that.

The routes.rb specifies the following resources:

ActionController::Routing::Routes.draw do |map|
map.resources :users do |user|
user.resource :blog
end

map.connect ‘:controller/:action/:id’
map.connect ‘:controller/:action/:id.:format’
end

Generated routes (only a subset):

POST /users/:user_id/blog {:controller=>“blogs”,
:action=>“create”}
POST /users/:user_id/blog.:format {:controller=>“blogs”,
:action=>“create”}
new_user_blog GET /users/:user_id/blog/new
{:controller=>“blogs”, :action=>“new”}
formatted_new_user_blog GET /users/:user_id/blog/new.:format
{:controller=>“blogs”, :action=>“new”}
edit_user_blog GET /users/:user_id/blog/edit
{:controller=>“blogs”, :action=>“edit”}
formatted_edit_user_blog GET /users/:user_id/blog/edit.:format
{:controller=>“blogs”, :action=>“edit”}
user_blog GET /users/:user_id/blog
{:controller=>“blogs”, :action=>“show”}
formatted_user_blog GET /users/:user_id/blog.:format
{:controller=>“blogs”, :action=>“show”}
PUT /users/:user_id/blog {:controller=>“blogs”,
:action=>“update”}
PUT /users/:user_id/blog.:format {:controller=>“blogs”,
:action=>“update”}
DELETE /users/:user_id/blog {:controller=>“blogs”,
:action=>“destroy”}
DELETE /users/:user_id/blog.:format {:controller=>“blogs”,
:action=>“destroy”}

The routes are exactly as we would like them. i.e. per user there is
only one blog.

The problem starts when trying to consume these resources using active
resource from a client application (ie another rails app to consume the
REST api resources). Here is a description of the models:

class User < ActiveResource::Base
self.site = “http://localhost:3000/
end

class Blog < ActiveResource::Base
self.site = “http://localhost:3001/users/:user_id/
end

CRUD operations for the User model work fine. No problem there. But on
inspection of the collection and element paths for the Blog model the
following urls are generated:

Blog.collection_path(:user_id => 1)
=> “/users/1/blogs.xml”

Blog.element_path(1, :user_id => 1)
=> “/users/1/blogs/1.xml”

On trying to create a blog for a specific user:

b = Blog.new(:params => {:user_id => 1})

b.save
ActiveResource::ResourceNotFound: Failed with 404 Not Found

the client application gets a 404 because the generated url is incorrect
and the REST API application throws an ActionController::UnknownAction
exception because the generated route is routed to the wrong controller
and action, in this case:

/users/1/blogs.xml

gets routed to the users controller and tries to execute the 1 action.
So, this cannot work, since the REST api cannot resolve these urls to
routes since we have specified a singular resource i.e. “blog”.

Can anyone help us with specifying how the consuming active resource
models generate the correct urls for a singular nested resource? As we
don’t want to change the api specification as it is proper and concise.

Thanks in advance for your time.