to nest or not to nest: RESTful style

In our world:   There are many landlords.   Landlords have many buildings.   Buildings have many tenants.

One way to structure the routes would be:

/landlords/:landlord_id /landlords/:landlord_id/buildings/:building_id /landlords/:landlord_id/buildings/:building_id/tenants/:tenant_id

... which certainly works. (Perhaps the only problem with this approach is that you need a really small font and a wide screen to see the output of 'rake routes' :slight_smile: But since each :building_id is unique among buildings, and :tenant_id is unique among tenants, you could also use "folded" routes:

/landlords/:landlord_id /buildings/:building_id /tenants/:tenant_id

Are there articles written (or strongly held opinions) on which approach is preferable, and why?

Thanks.

"Fearless Fool" <lists@ruby-forum.com> wrote in message news:87f41f7fcd6d2f7d85de9eb875505c8d@ruby-forum.com...

In our world: There are many landlords. Landlords have many buildings. Buildings have many tenants.

One way to structure the routes would be:

/landlords/:landlord_id /landlords/:landlord_id/buildings/:building_id /landlords/:landlord_id/buildings/:building_id/tenants/:tenant_id

... which certainly works. (Perhaps the only problem with this approach is that you need a really small font and a wide screen to see the output of 'rake routes' :slight_smile: But since each :building_id is unique among buildings, and :tenant_id is unique among tenants, you could also use "folded" routes:

/landlords/:landlord_id /buildings/:building_id /tenants/:tenant_id

Are there articles written (or strongly held opinions) on which approach is preferable, and why?

The first is good in that it allows you to not need to specify which landlord you want on the building creation form, since that is already in the url. But it is bad because it gives more information than is needed to identify some resources. It is also bad if you want to offer the option to change the landlord of a building.

The second is good in that there is never more information than is needed to identify resources. It is good if you want to let a tenant be moved to a new building in the tenant edit form. It is bad in that the forms for creating a resource require specifying the parent. (Imagine if when creating a comment for a blog post, the form required you to specify which story you were commenting on. Yuck!)

The best of both worlds is shallow routes. Using shallow routes, each URL is exactly as long as it needs to be to uniquely identify resources, while still letting you omit unnessiary feilds on your forms.

For your example you would use:

map.resources :landlords, :has_many => { :buildings => :tenants }, :shallow => true

Now to see landlord 5's buildings you go to /landlords/5/buildings

To create a new building for landlord 5 you go to /landlords/5/buildings/new

To view building 55 you go to /buildings/55.

To edit building 55 you go to /buildings/55/edit since rails already knows who the landlord is.

To view building 55's tenants you use /buildings/55/tenants

and so on.

Hope that helps.

Joe Smith wrote:

The best of both worlds is shallow routes. <snip> For your example you would use: <snip> map.resources :landlords, :has_many => { :buildings => :tenants }, :shallow => true <followed by lucid explanation of why this is useful> Hope that helps.

Very much. I've been playing with 'rake routes' and had arrived at this:

map.resources :landlords, :shallow => true do |landlord|   landlord.resources :buildings, :shallow => true do |building|     building.resources :tenants   end end

... which happens to generate an identical map. But Joe's mapping syntax much more concise, and his explanation is great.

Many thanks.

Fearless Fool wrote:

... which happens to generate an identical map. But Joe's mapping syntax much more concise, and his explanation is great.

I can't take full credit for the syntax. I found it in the "Rails Routing from the Outside In" guide [1] when double checking the syntax for shallow routes.

[1] Rails Routing from the Outside In — Ruby on Rails Guides

Joe Smith wrote:

The second is good in that there is never more information than is needed to identify resources. It is good if you want to let a tenant be moved to a new building in the tenant edit form. It is bad in that the forms for creating a resource require specifying the parent. (Imagine if when creating a comment for a blog post, the form required you to specify which story you were commenting on. Yuck!)

Upon further thought:

It *would* a pain if you had to specify the blog entry in order to post a comment. But the BlogComment model knows which BlogEntry it's part of. Thus the BlogCommentController can make @blog_entry available to the form so you don't have to.

Am I missing something?