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] http://guides.rubyonrails.org/routing.html

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?