# Nested Dynamic Routes

**URL:** <https://discuss.rubyonrails.org/t/nested-dynamic-routes/14746>\
**Category:** rubyonrails-talk\
**Created:** [June 22, 2007, 4:21am UTC](https://discuss.rubyonrails.org/t/nested-dynamic-routes/14746 "2007-06-22T04:21:56Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Daniel\_N](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@Daniel\_N](https://discuss.rubyonrails.org/u/Daniel_N)\
**Post date:** [June 22, 2007, 4:21am UTC](https://discuss.rubyonrails.org/t/nested-dynamic-routes/14746/1 "2007-06-22T04:21:56Z")

</div>

Hi,

I have a url scheme where I would like to include a public and private interface, and I have a nested resource for it.

The two schemes are

/my/books/pages /:username/books/pages

I would like to sperate the books and pages controllers into MyBooks, MyPages #=\> the user here will always be the currently logged in user and PublicBooks, PublicPages #=\> The users books will be whatever user is specified.

All public stuff is read only, although there will be a further nested resource on both (comments) that should be mapped to one controller to controll all comments, read and write.

I’m thinking at the moment that this will eliminate a lot of messy controller logic that tries to decide if I can access things or not, and tries to decide what user the context of the request is in etc.

The messiest that I can see this getting is if the user is accessing thier own book through a public interface and wants to say edit it. In this case I’m thinking of just re-directing to the edit action of the MyBooksController

I really don’t have a clue how to proceed here. Here’s what I’m thinking but I don’t believe this works.

map.resources :books :path\_prefix =\> ‘my’, :controller =\> ‘my\_books\_controller’ do books.resources :pages, :controller =\> ‘my\_pages\_controller’ do pages.resources :comments end end

map.resources :books :path\_prefix =\> ‘/:username’, :controller =\> ‘public\_books\_controller’ do

books.resources :pages, :controller =\> ‘public\_pages\_controller’ do

```
pages.resources :comments

```

end

end

Can anyone give a little advice please? Is this even a good way to go, or should I be looking elsewhere for a solution?

Cheers Daniel

---

<div class="post-metadata">

**Author:** ![Trevor\_Squires](https://avatars.discourse-cdn.com/v4/letter/t/848f3c/32.png) [@Trevor\_Squires](https://discuss.rubyonrails.org/u/Trevor_Squires)\
**Post date:** [June 22, 2007, 6:02am UTC](https://discuss.rubyonrails.org/t/nested-dynamic-routes/14746/2 "2007-06-22T06:02:23Z")

</div>

Hey,

I'm assuming that you're asking if using different controllers for  
those routes is the way to go.

Whenever I'm presented with those sorts of decisions, the strategy I  
reach for the most is "a separate controller for each map.resource(s)".

It's not always the strategy that I \*finish\* with, but I find it's  
always the best starting point.

Doing it like this stops me from over-generalizing too early. Once  
the controllers have all been written with their specific use-cases  
in mind ("Make it work"), everything is laid out in front of me. Any  
ways I can make things DRYer are blindingly obvious ("Make it right").

Sometimes I'll decide to pull something back into a single do- everything controller. Other times I'll just create a few mixins or  
maybe even an inheritance hierarchy to reduce duplication.

Nearly all of the time I'm just really grateful I resisted the  
temptation to start off saying "hey, these are the same so I can just  
use one controller!".

HTH, Trevor

---

<div class="post-metadata">

**Author:** ![Daniel\_N](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@Daniel\_N](https://discuss.rubyonrails.org/u/Daniel_N)\
**Post date:** [June 22, 2007, 6:22am UTC](https://discuss.rubyonrails.org/t/nested-dynamic-routes/14746/3 "2007-06-22T06:22:28Z")

</div>

I think what your suggesting is that what I’m contemplating isn’t too bad of an idea 😉

I guess what I’m really asking is not so much if the urls are right. But if the concept of splitting the controllers like this is correct for what I’m trying to achive. Ie having MY user resource, and a public interface to OTHERs resources.

If this is the way to go. I would like to generate the urls I listed since I think they are self explanitory. So then in that case are these routes on the right track?

/my/books/pages

/:username/books/pages

map.resources :books :path\_prefix =\> ‘my’, :controller =\> ‘my\_books\_controller’ do

books.resources :pages, :controller =\> ‘my\_pages\_controller’ do

```
pages.resources :comments

```

end

end

map.resources :books :path\_prefix =\> ‘/:username’, :controller =\> ‘public\_books\_controller’ do

books.resources :pages, :controller =\> ‘public\_pages\_controller’ do

```
pages.resources :comments

```

end

end

Thanx for you help

Daniel

---

<div class="post-metadata">

**Author:** ![Trevor\_Squires](https://avatars.discourse-cdn.com/v4/letter/t/848f3c/32.png) [@Trevor\_Squires](https://discuss.rubyonrails.org/u/Trevor_Squires)\
**Post date:** [June 22, 2007, 5:22pm UTC](https://discuss.rubyonrails.org/t/nested-dynamic-routes/14746/4 "2007-06-22T17:22:18Z")

</div>

> I think what your suggesting is that what I'm contemplating isn't too bad of an idea 😉
> 
> I guess what I'm really asking is not so much if the urls are right. But if the concept of splitting the controllers like this is correct for what I'm trying to achive. Ie having MY user resource, and a public interface to OTHERs resources.

Yeah, what I'm saying is: absolutely yes, start by splitting the controllers. You may end up consolidating them once you've fleshed everything out, but \*start\* by coding the controllers to deal with their specific use-cases in mind.

Once that's done, the opportunities for doing this "right" will be staring you right in the face because your \*code\* will be telling you how it should be architected, not some random guy spouting rubbish on a mailing list 🙂

I.e. you may look at the code and say "gee, all my urls should be /:username/books etc 'cause the only conditional would be a quick check to see if the current user name == :username to determine whether they can edit this resource". You won't know that for certain until all your moving parts are actually doing what they are supposed to do.

> If this is the way to go. I would like to generate the urls I listed since I think they are self explanitory. So then in that case are these routes on the right track?
> 
> /my/books/pages /:username/books/pages

Don't forget to make sure a user can't use the word 'my' as their username 🙂

HTH, Trevor

---

<div class="post-metadata">

**Author:** ![Daniel\_N](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@Daniel\_N](https://discuss.rubyonrails.org/u/Daniel_N)\
**Post date:** [June 23, 2007, 7:36am UTC](https://discuss.rubyonrails.org/t/nested-dynamic-routes/14746/5 "2007-06-23T07:36:01Z")

</div>

Thanx for the explianation.

At this stage it doesn’t seem as simple as a quick check because the required permission set makes it all a bit nasty together. Having said that, I currently have them all together and it smells a bit. Hence the question.

Thanx again. Daniel

---

<div class="post-metadata">

**Author:** ![Daniel\_N](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@Daniel\_N](https://discuss.rubyonrails.org/u/Daniel_N)\
**Post date:** [June 23, 2007, 2:27pm UTC](https://discuss.rubyonrails.org/t/nested-dynamic-routes/14746/6 "2007-06-23T14:27:06Z")

</div>

I’ve created a branch to modify my code to reflect this, and it has quite suddenly occured to me that this will make views very difficult to do and keep them DRY. I would need to duplicate my views for each controller because of the named routes.

For example and forms where I have

\<% form\_for @book do |f| %\>

No longer work since they look for a book\_path. If I then change this to a my\_book\_path in the routes, then my new public controller will not be able to use it.

This isn’t so bad for forms, since the public controller doesn’t have write access to anything and so these should never be rendered for it.

Where the issue lies is in the link generation. e.g.

\<%= link\_to @book.title, book\_url( @book ) -%\> needs to become my\_book\_url( @book ) OR public\_book\_url( @book ) depending on how it is accessed.

If I have to duplicate my views, or have a bunch of logic in every time I want to set a link, I don’t think I will change over since I think this would be messier in the long run.

Any ideas on how to avoid this?

Thanx Daniel

---

<div class="post-metadata">

**Author:** ![Daniel\_N](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@Daniel\_N](https://discuss.rubyonrails.org/u/Daniel_N)\
**Post date:** [June 23, 2007, 2:29pm UTC](https://discuss.rubyonrails.org/t/nested-dynamic-routes/14746/7 "2007-06-23T14:29:00Z")

</div>

Sorry if this comes twice. I’m having some trouble with gmail

> > > I think what your suggesting is that what I’m contemplating isn’t too bad of an idea 😉
> > > 
> > > I guess what I’m really asking is not so much if the urls are
> > 
> > > right. But if the concept of splitting the controllers like this is correct for what I’m trying to achive. Ie having MY user resource, and a public interface to OTHERs resources.
> > 
> > Yeah, what I’m saying is: absolutely yes, start by splitting the controllers. You may end up consolidating them once you’ve fleshed everything out, but _start_ by coding the controllers to deal with
> > 
> > their specific use-cases in mind.
> > 
> > Once that’s done, the opportunities for doing this “right” will be staring you right in the face because your _code_ will be telling you how it should be architected, not some random guy spouting rubbish on
> > 
> > a mailing list 🙂
> > 
> > I.e. you may look at the code and say "gee, all my urls should be /:username/books etc 'cause the only conditional would be a quick check to see if the current user name == :username to determine
> > 
> > whether they can edit this resource". You won’t know that for certain until all your moving parts are actually doing what they are supposed to do.
> > 
> > > If this is the way to go. I would like to generate the urls I
> > 
> > > listed since I think they are self explanitory. So then in that case are these routes on the right track?
> > > 
> > > /my/books/pages /:username/books/pages
> > 
> > Don’t forget to make sure a user can’t use the word ‘my’ as their
> > 
> > username 🙂
> > 
> > HTH, Trevor

> Thanx for the explianation.
> 
> At this stage it doesn’t seem as simple as a quick check because the required permission set makes it all a bit nasty together. Having said that, I currently have them all together and it smells a bit. Hence the question.
> 
> Thanx again. Daniel

I’ve created a branch to modify my code to reflect this, and it has quite suddenly occured to me that this will make views very difficult to do and keep them DRY. I would need to duplicate my views for each controller because of the named routes.

For example and forms where I have

\<% form\_for @book do |f| %\>

No longer work since they look for a book\_path. If I then change this to a my\_book\_path in the routes, then my new public controller will not be able to use it.

This isn’t so bad for forms, since the public controller doesn’t have write access to anything and so these should never be rendered for it.

Where the issue lies is in the link generation. e.g.

\<%= link\_to @book.title, book\_url( @book ) -%\> needs to become my\_book\_url( @book ) OR public\_book\_url( @book ) depending on how it is accessed.

If I have to duplicate my views, or have a bunch of logic in every time I want to set a link, I don’t think I will change over since I think this would be messier in the long run.

Any ideas on how to avoid this?

Thanx Daniel

---

<div class="post-metadata">

**Author:** ![Trevor\_Squires](https://avatars.discourse-cdn.com/v4/letter/t/848f3c/32.png) [@Trevor\_Squires](https://discuss.rubyonrails.org/u/Trevor_Squires)\
**Post date:** [June 25, 2007, 2:06am UTC](https://discuss.rubyonrails.org/t/nested-dynamic-routes/14746/8 "2007-06-25T02:06:22Z")

</div>

Hey,

comments inline:

> I've created a branch to modify my code to reflect this, and it has  
> quite suddenly occured to me that this will make views very  
> difficult to do and keep them DRY. I would need to duplicate my  
> views for each controller because of the named routes.
> 
> For example and forms where I have
> 
> \<% form\_for @book do |f| %\>
> 
> No longer work since they look for a book\_path. If I then change  
> this to a my\_book\_path in the routes, then my new public controller  
> will not be able to use it.
> 
> This isn't so bad for forms, since the public controller doesn't  
> have write access to anything and so these should never be rendered  
> for it.

Cool, so we can just ignore that one.

> Where the issue lies is in the link generation. e.g.
> 
> \<%= link\_to @book.title, book\_url( @book ) -%\> needs to become  
> my\_book\_url( @book ) OR public\_book\_url( @book ) depending on how  
> it is accessed.
> 
> If I have to duplicate my views, or have a bunch of logic in every  
> time I want to set a link, I don't think I will change over since I  
> think this would be messier in the long run.

Okay, first I'll give you the "roll your own, low-impact" version.

The important thing to remember is that book\_url etc are just  
methods. I'm guessing that you're not going to permit editing and  
deleting so really it's just book\_path(book) and books\_path() that  
are important at the moment. Note that I didn't say book\_url -  
because you really only need to use that for redirects (which implies  
editing, and the public controller doesn't need that).

Anyhow, in the public controller, you just do:

class PublicBooksController &nbsp;&nbsp;&nbsp;protected &nbsp;&nbsp;&nbsp;def book\_path(\*args) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public\_book\_path(\*args) &nbsp;&nbsp;&nbsp;end &nbsp;&nbsp;&nbsp;def books\_path(\*args) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public\_books\_path(\*args) &nbsp;&nbsp;&nbsp;end &nbsp;&nbsp;&nbsp;helper\_method :book\_path, :books\_path end

So any time a request that's being served by PublicBooksController  
sees a book\_path or books\_path call, it calls the relevant method.  
Now MyBooksController and PublicBooksController can use the same  
partials.

Now, there \*are\* times when you want to re-use views completely  
(rather than just sharing partials), and when it's much more than  
just book\_path or books\_path that you're calling. If this is one of  
those cases then I've got a plugin called resource\_fu which makes  
wiring that up much easier:

[http://agilewebdevelopment.com/plugins/resource\_fu](http://agilewebdevelopment.com/plugins/resource_fu)

But if the code I quote above is enough for you then I'd just stick  
with that.

HTH, Trevor
