It sounds like it is generally recommended either not to nest controllers at all or at most by one level. However this seems to relate mostly to resources. Interactive functionality generally works well with resources, but for a complete website there is often additional content that contains information not suitable for resources, but that still uses the same views mechanism for consistency.
I’ve got some resources and also some content that doesn’t suit using resources and it is convenient to store the content in hierarchical directories (?namespaces). The content is written as rails views. All worked OK under rails 2 but I’m struggling to get routing to work under rails 3.
For example if you have an app/views directory structure such as:
views >
level1
level2
level3
and would to place views at each of these levels, including an index action, what is the best way to create route(s) in routes.rb to accommodate this?
Using the default wildcard route of match ‘:controller(/:action(/:id(.:format)))’ results in the top level working but the index action for level2 results in an action not known for level1 controller from the router.
I’ve experiemented with various combinations of namespace, scope and match statements, but none seem to cater for this seemingly simple requirement to match a nested set of views to urls.
Maybe I’m missing a trick here - is there a better way to structure hierarchical non-resource content but still use the facilities in the rails framework? I guess I could combine rails with some other framework, but would like to keep everything within rails if possible.
Don’t suppose anyone has a moment to give me a pointer on this one?
I’ve tried the following:
namespace “levelx” do
namespace “levely” do
namespace “levelz” do
root :to => ‘levelz#index’
end
root :to => ‘levely#index’
end
root :to => ‘levelx#index’’
end
This provides default routes for each namespace, but you then can’t access any other controllers at each level of namespace. You can’t specify a :controller segment, so adding match “:controller(/:action)” within each namespace block is not an option.
I’ve also tried:
match ‘/levelx/levely/levelz/:controller(/:action)’
match ‘/levelx/levely/levelz’ => ‘levelx/levely/levelz#index’
match ‘/levelx/levely/:controller(/:action)’
match ‘/levelx/levely’ => ‘levelx/levely#index’
match ‘/levelx/:controller(/:action)’
match ‘/levelx’ => ‘levelx#index’
Which again seems to route index actions OK but not other controllers within each namespace.
I’ve tried:
match ‘/levelx/levely/levelz/:controller(/:action)’, :controller => /levelx/levely/levelz*/
match ‘/levelx/levely/:controller(/:action)’, :controller => /levelx/levely*/
match ‘/levelx/:controller(/:action)’, :controller => /levelx/levely*/
match ‘/:controller(/:action)’, :controller => /levelx*/
Which doesn’t seem to work.
What I’m really after is the equivalent of the match ‘/:controller(/:action)’ that will work with nested namespaces. If constraints can be applied to top level namespaces then so much the better.
Maybe time to admit defeat and abandon rails for this type of website, which would be a shame since the rails framework is great for teh rest of the resource-based parts of the site. More likely I’m just being thick.
The problem is very specific, so would be hard to quickly find a solution with the information you have posted.
Would be good if you can post the routes file from your Rails 2 app which used to work fine and the best working version of routes file from Rails 3 app.
namespace "levelx" do
namespace "levely" do
namespace "levelz" do
match 'levelzcontrollerone(/:action)' => 'levelzcontrollerone#'
match ':action' => '#'
root :to => 'levelz#index'
end
match 'levelycontrollerone(/:action)' => 'levelycontrollerone#'
match ':action' => '#'
root :to => 'levely#index'
end
match 'levelxcontrollerone(/:action)' => 'levelxcontrollerone#'
match ':action' => '#'
root :to => 'levelx#index'
end
Don’t suppose anyone has a moment to give me a pointer on this one?
I’ve tried the following:
namespace “levelx” do
namespace “levely” do
namespace “levelz” do
root :to => 'levelz#index'
end
root :to => 'levely#index'
end
root :to => ‘levelx#index’’
end
This provides default routes for each namespace, but you then can’t access any other controllers at each level of namespace. You can’t specify a :controller segment, so adding match “:controller(/:action)” within each namespace block is not an option.
I’ve also tried:
match ‘/levelx/levely/levelz/:controller(/:action)’
match ‘/levelx/levely/levelz’ => ‘levelx/levely/levelz#index’
match ‘/levelx/levely/:controller(/:action)’
match ‘/levelx/levely’ => ‘levelx/levely#index’
match ‘/levelx/:controller(/:action)’
match ‘/levelx’ => ‘levelx#index’
Which again seems to route index actions OK but not other controllers within each namespace.
I’ve tried:
match ‘/levelx/levely/levelz/:controller(/:action)’, :controller => /levelx/levely/levelz*/
match ‘/levelx/levely/:controller(/:action)’, :controller => /levelx/levely*/
match ‘/levelx/:controller(/:action)’, :controller => /levelx/levely*/
match ‘/:controller(/:action)’, :controller => /levelx*/
Which doesn’t seem to work.
What I’m really after is the equivalent of the match ‘/:controller(/:action)’ that will work with nested namespaces. If constraints can be applied to top level namespaces then so much the better.
Maybe time to admit defeat and abandon rails for this type of website, which would be a shame since the rails framework is great for teh rest of the resource-based parts of the site. More likely I’m just being thick.
Many thanks for any thoughts.
As a Rails best practice, I would recommend that you don’t nest routes that are more than two levels deep.