# REST - Nested Resources

**URL:** <https://www.ruby-forum.com/t/rest-nested-resources/137686>\
**Category:** Rails\
**Created:** [May 15, 2008, 10:30am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686 "2008-05-15T10:30:45Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 15, 2008, 10:30am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/1 "2008-05-15T10:30:45Z")

</div>

Hi

I am trying to use RESTful design practices, but I have areas of the  
design which seem to suggest that I should have more than one level of  
nesting. Now, all of the reading I have done, tells me that this is a  
very bad idea, so I was wondering if the esteemed memebers of the list  
can help me out.

One example:

There are many goals.  
Each goal has many milestones.  
Each milestone belongs to one user.

The UI is going to make fairly heavy use of AJAX to update elements, and  
that will lead to situations where I need to get the following:

All Milestones for a particular user and a particular goal.

Now, if I go crazy with the nesting, I would end up with this as a url:

/goal/goal\_id/user/user\_id/milestones

Can anyone suggest RESTful alternatives, that won’t violate the best  
practice of only one level of nesting?

Thanks in Advance

Rory

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 15, 2008, 7:04pm UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/2 "2008-05-15T19:04:52Z")

</div>

Rory McKinley wrote:

> There are many goals.  
> /goal/goal\_id/user/user\_id/milestones
> 
> Can anyone suggest RESTful alternatives, that won’t violate the best  
> practice of only one level of nesting?
> 
> Thanks in Advance
> 
> Rory

No matter how you setup your routes, the milestones controller is going  
to be the entry point, and it’s going to need a :user\_id and :goal\_id in  
params (unless you’re going to also allow just one or the other).  
You’re only RESTfulish route options that I can think of are…

1. /goals/#/milestones?user\_id=#
2. /users/#/milestones?goal\_id=#
3. /users/#/goals/#/milestones
4. /goals/#/users/#/milestones

If the typical use of this application would be users looking at their  
own milestones, then opt 2 is probably what I would go with. Then  
users/#/milestones could be a list of _all_ of that user’s milestones,  
and they could then choose a ‘goal’ to _filter_ the list. That also  
opens the door for option 1, so that someone could see all of the  
milestones for a goal, and filter them by user.

What I think it boils down to is which seems to make the most sense  
based on how the data will be visualized. I’ve occasionally used deeply  
nested routes for certain actions, but only in cases where it really  
made sense (at least to me) to do so. All of the above 4 options are  
technically legal, so… it’s really just a matter of preference.

Note however that I used the _plural_ versions of ‘user’ and ‘goal’ in  
my sample routes. Using plural names in your routes and controllers is  
(to the best of my knowledge) standard and recommended convention.

–

[http://www.5valleys.com/](http://www.5valleys.com/)

[http://www.workingwithrails.com/person/8078](http://www.workingwithrails.com/person/8078)

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 12:00am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/3 "2008-05-16T00:00:43Z")

</div>

Surely you don’t need to know all three objects at the same time. If you  
cared so much about restful routing you would simply reference the other  
objects through the relationships.

Can you explain why you need to reference all three at the same time?

On Fri, May 16, 2008 at 2:33 AM, Jon G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > One example:  
> > Now, if I go crazy with the nesting, I would end up with this as a url:
> 
> If the typical use of this application would be users looking at their  
> technically legal, so… it’s really just a matter of preference.
> 
> >

–  
Ryan B.

> **[frozenplague.net](http://www.frozenplague.net)**
>
> This domain may be for sale!

Feel free to add me to MSN and/or GTalk as this email.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 7:33am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/4 "2008-05-16T07:33:29Z")

</div>

Ryan B. (Radar) wrote:

> Surely you don’t need to know all three objects at the same time. If you  
> cared so much about restful routing you would simply reference the other  
> objects through the relationships.
> 
> Can you explain why you need to reference all three at the same time?

For the purposes of satisfying the UI requirements, I, at some point,  
have to fetch a subset of a goal’s milestones. This subset will be all  
those milestones for a particular goal and are being worked on by a  
particular user (note that this is not necessarily the user that is  
currently logged in).

To satisfy this, without knowing in advance the milestone ids, I have to  
pass the milestone controller both a goal id and a user id. The  
milestone belongs to both a goal and an user.

If you can tell me of a way that I can do this without passing both of  
those parameters in an ajax request, I would be extremely grateful.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 7:47am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/5 "2008-05-16T07:47:32Z")

</div>

Jon G. wrote:

> 1. /goals/#/milestones?user\_id=#
> 2. /users/#/milestones?goal\_id=#
> 3. /users/#/goals/#/milestones
> 4. /goals/#/users/#/milestones

I think (1) and (2) will probably be the way I will need to go. I don;t  
have the Rails/REST experience so I will rather err on the side of  
something that is easier to maintain.

Although, wouldn’t (1)and (2) be somewhat less self-documenting than (3)  
and (4)? Thereby losing some of the advantages of REST. Or am I missing  
the point?

\> Note however that I used the \*plural\* versions of 'user' and 'goal' in \> my sample routes. Using plural names in your routes and controllers is \> (to the best of my knowledge) standard and recommended convention.

Apologies that was a haste-induced error on my part.

Thanks for the help - it cleared a lot of things up.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 8:23am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/6 "2008-05-16T08:23:19Z")

</div>

Ryan B. (Radar) wrote:

> Can you show me your models so I can get a clearer understanding of the  
> layout? Thanks. Just the relationships.

class User \< ActiveRecord::Base has\_many :goals has\_many :milestones

class Milestone \< ActiveRecord::Base  
belongs\_to :goal  
belongs\_to :user

class Goal \< ActiveRecord::Base  
belongs\_to :user  
belongs\_to :category  
has\_many :milestones

here ya go

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 8:27am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/7 "2008-05-16T08:27:27Z")

</div>

map.resources :goals do |goal|  
goal.resources :milestones  
end

map.resources :milestones

map.resources :users do |user|  
user.resources :goals  
user.resources :milestones  
end

That should be all you need to do.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 8:53am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/8 "2008-05-16T08:53:20Z")

</div>

Ryan B. (Radar) wrote:

> That should be all you need to do.  
> \<I am assuming that for the above, the additional parameter required -  
> e.g. user\_id in the case of /goals/#/milestones, would be passed as a  
> get parameter? I.e. /goals/#/milestones?user\_id=#

Is that correct?

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 7:41am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/9 "2008-05-16T07:41:41Z")

</div>

Can you show me your models so I can get a clearer understanding of the  
layout? Thanks. Just the relationships.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 9:06am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/10 "2008-05-16T09:06:53Z")

</div>

Because a goal belongs to a user you can get the user by doing  
@goal.user,  
you don’t need to pass in the user\_id variable.

On Fri, May 16, 2008 at 4:22 PM, Rory McKinley  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > user.resources :milestones

–  
Ryan B.

> **[frozenplague.net](http://www.frozenplague.net)**
>
> This domain may be for sale!

Feel free to add me to MSN and/or GTalk as this email.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 9:24am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/11 "2008-05-16T09:24:30Z")

</div>

Ryan B. (Radar) wrote:

> Because a goal belongs to a user you can get the user by doing  
>   
> Ah.

Apologies - that, I had forgotten to mention - the user that owns the  
goal is not necessarily the user that owns the milestone:

E.g. Goal 1 belongs to User 1

Milestone 1 belongs to Goal 1 and is being worked on by User 2 and hence  
belongs to User 2  
Milestone 2 belongs to Goal 1 and is being worked on by User 3 and hence  
belongs to User 3  
Milestone 3 belongs to Goal 1 and is being worked on by User 1 and hence  
belongs to User 1

In terms of filtering the milestones, the user that works on the  
milestone is the user that I am interested in.

Sorry about that 😉

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 9:26am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/12 "2008-05-16T09:26:18Z")

</div>

And a milestone is assigned to a user, so you can go to  
/goals/1/milestones/2 and then do @milestone.user to get the user.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 9:59am UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/13 "2008-05-16T09:59:11Z")

</div>

Ryan B. (Radar) wrote:

> And a milestone is assigned to a user, so you can go to  
> /goals/1/milestones/2 and then do @milestone.user to get the user.

But what if I want to request "all goal 1's milestones that belong to user 3"?

If I don’t pass a user\_id parameter to goals/1/milestones, I then have  
to filter out the milestones that have user\_id = 3 client-side using JS.

My problem is not so much getting the result set, it’s setting up the  
routing so that I can make the request in a RESTful manner.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 12:57pm UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/14 "2008-05-16T12:57:23Z")

</div>

On May 16, 12:58 pm, Rory McKinley [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Ryan B. (Radar) wrote:
> 
> > And a milestone is assigned to a user, so you can go to  
> > /goals/1/milestones/2 and then do @milestone.user to get the user.
> 
> But what if I want to request "all goal 1's milestones that belong to user 3"?

For this, you need to have a conditions parameters in your GET REST  
call like this:

GET /goals/1/milestones.xml?condditions=user\_id=3  
Now in your index method, do this:  
params[:conditions] = params[:conditions] + '“AND  
(#{params[:conditions]})”

@milestones = MileStone.find(:all, :conditions =\>  
params[:conditions])

# And that’s it.

However, watch out for the SQL injection attacks! make your code safe  
I’ve just demonstrated the idea.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 12:53pm UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/15 "2008-05-16T12:53:16Z")

</div>

/goals/1/users/3/milestones/

On Fri, May 16, 2008 at 5:28 PM, Rory McKinley  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> to filter out the milestones that have user\_id = 3 client-side using JS.
> 
> My problem is not so much getting the result set, it’s setting up the  
> routing so that I can make the request in a RESTful manner.
> 
> >

–  
Ryan B.

> **[frozenplague.net](http://www.frozenplague.net)**
>
> This domain may be for sale!

Feel free to add me to MSN and/or GTalk as this email.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 1:03pm UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/16 "2008-05-16T13:03:54Z")

</div>

Ugh my god that is ugly!

My way is much simpler, but requires 2 level deep nested routing which  
shouldn’t be used unless it’s an extreme case, like this one.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 1:34pm UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/17 "2008-05-16T13:34:32Z")

</div>

Ryan B. (Radar) wrote:

> My way is much simpler, but requires 2 level deep nested routing which  
> shouldn’t be used unless it’s an extreme case, like this one.

Jon’s mail earlier in the thread, showed some ways that it can be done  
without the second level of nesting (which I was trying to avoid)

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 3:01pm UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/18 "2008-05-16T15:01:58Z")

</div>

Dont avoid it if it’s neccessary, the world will not hate you for it.

On Fri, May 16, 2008 at 9:03 PM, Rory McKinley  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> >

–  
Ryan B.

> **[frozenplague.net](http://www.frozenplague.net)**
>
> This domain may be for sale!

Feel free to add me to MSN and/or GTalk as this email.

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 7:33pm UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/19 "2008-05-16T19:33:44Z")

</div>

AndyV wrote:

> > But what if I want to request “all goal 1’s milestones that belong to  
> > user 3”?  
> > Can you come up with a real use case for your  
> > application in which you will need to provide the information in this  
> > way?  
> >   
> > Sadly, I have an actual use case for such a model 😉  
> >   
> > opinions of some, this is fully RESTful.

Thanks - I hadn’t thought it through fully - but what you are saying  
makes sense - an approach as suggested above would definitely produce  
much cleaner code.

Which leads me to a few more questions:

1. Can I map a resource both as a nested resource as in the  
user/milestones example as well as just /milestones? Or is that crazy  
talk? 🙂
2. Is it RESTful to pass more than one filter parameter? For instance  
just have /milestones and pass both goal\_id and user\_id? Although that  
would make the resulting controller code a lot uglier…
3. Can anybody recommend a good advanced reference on rails and rest?  
Most of the examples I have found have either been very basic or just  
touched on the advanced stuff. Currently about the best resource I have  
found is The Rails Way by Obie F…

Thanks to everyone who has helped so far… I am learning a stack.

R

---

<div class="post-metadata">

**Author:** ![Rory\_McKinley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/6bbea6/32.png) [@Rory\_McKinley](https://www.ruby-forum.com/u/Rory_McKinley)\
**Post date:** [May 16, 2008, 5:39pm UTC](https://www.ruby-forum.com/t/rest-nested-resources/137686/20 "2008-05-16T17:39:40Z")

</div>

> But what if I want to request “all goal 1’s milestones that belong to  
> user 3”?

Do you want to do that? What I mean by the question is that you  
really need to think through the _business_ that you are trying to  
model. Often we can get so distracted by the theoretical  
possibilities that we never finish with the practical realities of the  
tasks at hand. Can you come up with a real use case for your  
application in which you will need to provide the information in this  
way?

Can you frame the question in a different way that better maps to your  
general solution? For example, you might be able to conceive of  
this theoretical question of “all goal 1’s milestones that belong to  
user 3” instead as “which of user 3’s milestones are specifically  
related to goal 1”. Since your most common use case is (likely) the  
need to show the milestones for a particular (logged in) user the  
rephrased question might lead you to think of goal 1 becoming a  
_filter_ on the user\_milestones\_path routes. The UI might provide the  
context for identifying the user and goal and then you’d build up  
user\_milestones\_path(@user, :goal\_id=\>@goal.id). Contrary to the  
opinions of some, this is fully RESTful.

MilestonesController:  
def index  
@user = User.find\_by\_id params[:user\_id]  
@milestones = params[:goal\_id] ?  
@user.milestones.find(:all, :conditions=\>{:goal\_id=\>params[:goal\_id]}) :  
@user.milestones

…  
end

[Next page](https://www.ruby-forum.com/t/rest-nested-resources/137686.md?page=2)
