generated urls within namespaced controllers

Hello,

I've run across an issue with namespaced controllers and url generation.

From http://github.com/rails/rails/tree/master/actionpack/lib/action_controller/routing/route_set.rb
(line 322) I'm wondering what the purpose of the section of code with
this comment is:

# if the controller has changed, make sure it changes relative to the
# current controller module, if any. In other words, if we're currently
# on admin/get, and the new controller is 'set', the new controller
# should really be admin/set.

My scenario is the following...

I have view layout code with link_to's the use a hash to specify the url

link_to 'Example', {:controller => 'nonamespace', :action => 'index'}

which generates "/nonamespace"

But when I access a controller that is namespaced such as
"/namespace/blah/action", that same link_to now generates
"/namespace/nonamespace"

So from what I can tell the routing code is making an assumption that
I don't think it should which seems to be that generated urls
(sepcified with a hash) should remain in the context of the current
views controller. In my case it's code for a layout which can apply
to many controllers, so this assumption is incorrect and causing this
issue.

Can somebody explain the assumption made by the routing code and if
this is indeed a bug?

Thanks,
Andrew

Whether it's a bug or not is kind of a matter of interpretation. But
the *original intention* here was to support nested controllers with
relative links. So, f.ex:

Admin
- UsersController
- TagsController
UsersController

If you're in admin/tags/somethign and link to :controller=>'users'.
Where is it meant to go? With the current behaviour it will go to
/admin/users which is 'probably' a reasonable assumption.

You can work around this with :controller=> '/nonamespace' which will
work from anywhere.

I'm interested in people's opinions on this one, we can't really
change it for 2.2, but for the 2.3.x series we could try and
rationalise all this stuff.

+1 to the current behaviour... it's just like accessing a relative
file path vs an absolute one.

Cheers.

Except that using "/" for absolute vs nothing for relative has never
been a recommended approach when working with parameterized (hash)
urls. There is A LOT of code (almost certainly a valid assumption)
that does not use the "/" method of specifying the controller (which
is what I have used at the moment) and this nesting behaviour will
certainly break that code as soon as a nested controller is used.

For me a nested controller is the exception to the norm, not the other
way around.

-1 to the current behavior.

Except that using "/" for absolute vs nothing for relative has never
been a recommended approach when working with parameterized (hash)
urls. There is A LOT of code (almost certainly a valid assumption)
that does not use the "/" method of specifying the controller (which
is what I have used at the moment) and this nesting behaviour will
certainly break that code as soon as a nested controller is used.

It's actually been the recommended approach since before 1.0 shipped.
This behaviour has been around for a long long time, and we'd need an
alternative way to distinguish between the nested and non-nested
controller if we were to change it.

For me a nested controller is the exception to the norm, not the other
way around.

-1 to the current behavior.

What solution do you have in mind?

I've been using Rails almost since it's inception and have never seen
reference to using "/blah" as the recommended approach. If it was the
recommended approach, I'd expect the docs and books to use the
"absolute" style as well, but they don't use it.

I just took a look at the url_for and link_to docs. There is nothing
to suggest using "/" in link_to, but the closest I found was in the
url_for docs was "If the controller name begins with a slash, no
defaults are used: url_for :controller => '/home'"

So ok, it may have been a recommended approach, but there's almost no
reference to it. I didn't figure out to use "/" myself until I looked
at the code.

Regarding a solution I have in mind, I'm not really sure. Since
nested controllers are a lot less common in practice, my thoughts are
towards fixing that end of the stick. Would passing :nested => true
be a somewhat acceptable approach? That's just a quick thought that
springs to mind.

Andrew

I've been using Rails almost since it's inception and have never seen
reference to using "/blah" as the recommended approach. If it was the
recommended approach, I'd expect the docs and books to use the
"absolute" style as well, but they don't use it.

I think that the non-existent documentation for routes won't provide a
valid precedent for any argument. Essentially nothing was documented,
so looking for justification for anything in there is a sure road to
frustration.

Regarding a solution I have in mind, I'm not really sure. Since
nested controllers are a lot less common in practice, my thoughts are
towards fixing that end of the stick. Would passing :nested => true
be a somewhat acceptable approach? That's just a quick thought that
springs to mind.

I realise the result can be surprising if this is the first time
you've used modules, but we can't go breaking every application that
uses this functionality without good cause. This really is just a
question of relative or absolute paths, and everything I can think of
defaults to relative.

File.open("tmp") doesn't default to /tmp. <a href="index.html">
doesn't default to /index.html.

I don't see why routes should be any different.

However in your case, the route points to some nonsense controller
that doesn't even exist. We could change *that* behaviour without
breaking anything.

However in your case, the route points to some nonsense controller
that doesn't even exist. We could change *that* behaviour without
breaking anything.

That was my other thought actually as well; check the controller
"name" to see if it actually exists.

To me this seems like a pretty good compromise. I doubt anyone's
expecting url_for to point to non-existent controllers, and if they
are, it's hardly unreasonable for this to be fixed.

This will involve a trip into the bowels of the routes implementation,
but hopefully you come up better for the experience :slight_smile:

however...

<a href="missing.html"> is still non-existant... it doesn't take a
look around for /missing.html as well

...and, this would also mean that an admin/users controller which
referenced a url_for :controller => 'pages' would access /pages up
until the moment you add admin/pages and then the behaviour would
change.

too much magic for my liking.

document the existing behaviour properly and it is consistent (and
well documented).

cheers.

Heh, you've got two for the price of one, url_for and guide :-):

http://github.com/lifo/docrails/commit/1915d7ccce99a35c1a5e95e639760168a4bcc99f
http://github.com/lifo/docrails/commit/8a2820ada320a3bc7fcf8c6f3513d10039d650ad

I think the first time I saw this was in the source code of
acts_as_authenticated.