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 F.” [email protected] wrote in
message news:[email protected]

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 S. wrote:

The best of both worlds is shallow routes.

For your example you would use:

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

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 F. 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 S. 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?

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs