Hatred towards Nested Polymorphic Paths

I have a real grudge against the new nested polymorphic path magic stuff. I feel it encourages and gives people an excuse to write overly compelled routes. Resources should NOT be nested more than one level deep.

"/companies/1/people/1" == BAD "/people/1" == GOOD

I have no problem with nested collections.


You shouldn't need to be scoping person #1 if its the unique id.

I've seen alot of defect and enhancement tickets going by Trac showing its immaturity and lack of real need. None of this stuff has been merge with the stable, so its not to late to change things. It should really be pulled from Edge and into a plugin, "nested_polymorphic_paths".

Its not in the spirit of Rails to be providing tools to help you practice bad habits.

I tend to agree with this. I don't really understand the need to "canonically" identify a resource based on its context.

Other thoughts?


I wondered about the usefulness of this one too when it came out. But I in fact have a situation where I feel it is warranted to have the nested routes like this.

Each user has a collection of books. Each book has a collection of clips.

Clips can be shared between books. A Clip has a default view depending on which book your in when your looking at it. ( Data kept in the join model of the :through association )

This makes it important to have both pieces of information. This is I believe the same for any has_many :through association where you have additional information in the join model. Without both pieces of information you can’t identify the correct join model to use and therefore the extra piece of information you need.

Please let me know if there is another way to do what I’m suggesting.

Cheers Daniel

The simple reason would be that you want your URLs to look that way.


Whats the join model in this case? Can you pastie the example? (http:// pastie.caboo.se/)

Because each clip (and every other model you mentioned) has its own unique id, you can always use that to find it.

"/companies/1/people/1" == BAD "/people/1" == GOOD

You shouldn't need to be scoping person #1 if its the unique id.

Its not in the spirit of Rails to be providing tools to help you practice bad habits.

I think this is going too far. I too prefer to limit the scope to one level, but there are legitimate reasons to have deeper nesting. / albums/45/tracks/1 (where the track number is scoped on the album). Or closer to home, /forums/5/threads/1 and /forums/15/threads/1.

I think it's perfectly fine to encourage people to not nest when they don't really care one way or another. But to outright "forbid" it is pushing it.

What are your technical grudges against this? And what would be better if we didn't support it?

> I tend to agree with this. I don't really understand the need to > "canonically" identify a resource based on its context.

> Other thoughts?

The simple reason would be that you want your URLs to look that way.

I think this is also a reasonable argument. Again, I'm actually in the camp of it "not being worth it" from an effort/gain perspective to do fully nested URLs, but I don't want to push that dictate on someone else. The URL is half-ways part of the UI design and I'm very hesistant to push UI conventions on anyone.

Rails applications should be able to look completely incognito.

I think Josh’s grudge is against:

/tracks/219 == /albums/45/tracks/219

… where the track id is the unique ID of the track. This is perfectly fine with me, on the other hand:


… but then we’re talking about composite primary keys, which aren’t popular amongst Rails devs.

I wasn't clear about banning what..

I wanted to remove the whole polymorphic nesting with an array: polymorphic_path([@artist, @album, @track]). If you want to do something like that, use the old school named route for it: artist_album_track_path(@artist, @album, @track). I've seen a ton of tickets of people trying to extend polymorphic_path([...]) to do everything for them when a proper work around with named routes will do.

So, are you saying that, instead of doing this:

link_to @track.name, [@album, @track]

...we should be required to do this:

link_to @track.name, album_track_path(@album, @track)


I'm saying you should be doing ...

link_to @track.name, @track

Like I said, [@album, @track] is giving you an excuse to use complex routing patterns.

I think a case can be made for using an [@album, @track] nested route -- say a user browsed to album 45, and then clicked track 219 -- if your UI requires a "back to album 45" navigational link on the track page, you couldn't infer the referring album id from the resource id alone if there's a many-to-many relationship between albums and tracks -- instead, you'd need to grab the album id from the URI.

If your referring to a HABTM relationship, look into creating a real join model between them using has many though. That why you have a real resource you can point your url to.

Since you are so passionate about nested polymorphic resource, it seems like a perfect fit for you to make and maintain a plugin for this.

I gotta agree here. Presuming that people should always use root-level routes is going too far. The URL carries a lot of information, and why shouldn't the developer have access to it? Plus I don't really see how this polymorphic routing magic has much effect on people's design decisions. I don't think anyone is going to arbitrarily choose nested routing just because they don't have to use a named helper. There are so many other considerations at play, and jamming an array into link_to is not exactly magically delicious.

It sounds like the real issue is that there are too many patches and too many bugs to manage. Well if it can't be implemented cleanly then maybe it should be pulled. But the whole "encouraging bad practices" seems spurious.

Another point I was trying to make. If it was pulling into a plugin and matured a little, it could then be considered for reentry.

Can you please point out to tickets related to the issue ? They'd surely provide a better insight to your point.

Thanks, Pratik

Heres a few: [7152], #8725, #8782, #8719, #8720, #8705, #8830, #8654, #8640

I'm working on a project now, where we have things like:

/album/1/tracks /tracks #=> not valid /tracks/1 #=> valid /tracks/1/artists #=> Assume a track has many artists /artists/1/tracks #=> reverse of above; all the tracks for an artist.

Basically, we want `/foo/x/bar` to be valid, but not `/foo/x/bar/y`. And we want `/bar/y` to be valid, but not `/bar`. We're finishing up a plugin that defines those partial routes: index and create as nested resources, and show, edit and delete as non-nested.

I can’t pastie it unfortunately but it. But I believe it goes for any time you use a has_many :through relationship with additional data in the join table. Without both sides of the join, you can’t identify join, and therefore don’t have access to the extra data.

In my case it’s a view setting.

As another example,

users have mailboxes, and each mailbox can have many postcards Mailboxes → Postcards

Postcards are shared between users and mailboxes. One use likes to see a particular postcards picture, whilst one likes to see it’s text. The only place to put this view information that I can see is in the join table between the postcard and mailbox.

With this situation you need both the mailbox and the clip id to determine what view state the postcard should be in. The nested routes fit this perfectly.