Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: how to RESTful query models through associations?

I'm not getting REST with Ruby on Rails, and I'm hoping someone here can set me straight.

Imagine that I'm building a site that keeps track of Widgets and the Users that own those Widgets. So I'd have a UsersController and a WidgetsController, and I could get a list of Widgets or Users with the index actions:

GET /users
GET /widgets

and I could get a specific User or Widget with the show actions:

GET /users/id
GET /widgets/id

That much I understand.

Where I'm getting confused is what RESTful request would I use to retrieve a list of Widgets belonging to a specific User? Is that a request sent to the UsersController or the WidgetsController? Which of the 7 RESTful actions does it use?

Is one of those situations where I'd create a custom action? I was under the impression that custom actions are supposed to be rare, but this seems like a pretty common use case.

Thanks!

like image 416
Stewart Johnson Avatar asked Aug 11 '09 01:08

Stewart Johnson


1 Answers

The url for the list of widgets belonging to a user foo would look like this:

/users/foo/widgets

You then have a choice of how to do your URLs for each of those widgets. This is possible:

/users/foo/widgets/bar

But I prefer this:

/widgets/bar

Your routes would look like this:

map.resources :users, :has_many => :widgets, :shallow => true
map.resources :widgets, :has_many => :users, :shallow => true

(This is from memory, I may have screwed up one or more details)

The controller method that handles /user/foo/widgets is the index action of the WidgetController. It tests for the existence of the user_id parameter and restricts the widgets returned based on that. (Or retrieves the foo user and sets @widgets to @user.widgets.)

Update: There's a good overview of nested routing that answers my original question in the Rails Guides.

Update 2 Oh yes, I meant to link to some documentation as well.

like image 150
wombleton Avatar answered Oct 18 '22 19:10

wombleton