Rails 3.1 Engine namespaces can creep into URLs in application layout

By Zach Dennis on 22 Sep 2011

With Rails 3.1 Engines it is possible for the namespace to creep into the URL generation for your application layouts. This can occur if you are not using named routes, but instead are specifying :controller in an options Hash.

With Rails 3.1 Engines it is possible for the namespace to creep into the URL generation for your application layouts. This can occur if you are not using named routes, but instead are specifying :controller in a options Hash:

This issue will manifest itself onto other areas being rendered from the layout that relied on things like Rails current_page? and url_for helpers since under the hood they all rely on the same route generation logic.

To fix this you can replace any non-named routes with named routes:

Now you can use foo_path instead of relying on passing around :controller into any helper that generates a route which is cleaner and preferable IMO.

Why Does This Happen?

ActionDispatch::Routing::RouteSet tries to determine if a route is relative and if it is it will try to properly namespace the route based on current controller context. From Rails actionpack/lib/action_dispatch/routing/route_set.rb

It explicitly checks to see if we're dealing with a named_route. If so, it won't try to massage the route. This is why using an explicit controller in route generation is susceptible to this issue.

Next, it looks to see if we're in a different controller, which for engines will always be the case since they are namespaced in their own module.

After that, the massaging occurs and thats when the problem occurs.

Easy fix though, use named routes.

Is this a bug?

It might be, but I don't think it is. I think it is just how the Rails Engines have been designed to work in 3.1.