Implementing URLs with more than 3 levels in Rails


#1

Hi There

I started using Rails recently, and I see it’s very easy for URLs that
have up to 3 levels:

/:controller/:action/:id

But what do you do when you need more than 3?

For example, my current project should have an “admin” interface.
Admin has several sub-interfaces, for example a “users” interface. And
the admin/users interface has several actions, e.g. “add”, for each
user ID.

Ideally, I’d like to be able to have URLs such as:

www.example.com/admin/users/add/1

But this doesn’t seem to work very well with the Rails scheme and
supporting methods, for example “link_to” assuming :action in this
case is “users”, :id is “add”, and 1, well, doesn’t exist :slight_smile:

(of course it’s possible to have the “admin” namespace inferred from a
session, but I’d like a more RESTful approach)

Would appereciate any tips of good ways to do this.


#2

www.example.com/admin/users/add/1

You can do this. The question is, how are you going to lay out the
controllers? Will you have an admin_users controller? Using routes, you
could do:

map.connect ‘admin/users/:action/:id’, :controller => “admin_users”

and you’d get what you wanted.

I believe there’s also a way to put controllers in a subfolder, but I
have no experience with that. Anyone want to comment?


#3

Here’s an example I use to add the pagination parameters to the url

we are going to add the pagination parameters to the url instead of

adding them as parameters

this fixes alot of the caching problems

map.connect ‘pragmatic/:action/:id/:page’,
:controller => ‘pragmatic’,
:requirements => { :page => /\d+/},
:page => nil

adding more than three parameters to a url is as simple as creating the
route.

Charlie B.
http://www.recentrambles.com


#4

Like Maurice said you can do “script/generate controller Admin/User” and
you will get user_controller.rb file in app/controllers/admin folder.
Just remember that you can’t have admin_controller.rb in app/controllers
folder because it’s aleady the name of your group of controllers and
you’ll get errors.

If you need some common functionality for all your admin controllers you
could create admin_something.rb controller in app/controllers with
common functionality and inherit all other admin controllers from that.

This way you won’t have to mess with routes at all.


#5

This is done using modules.

For example,

create a file, /app/controllers/admin/user_controller.rb

and just make sure that in this file, UserController is inside the Admin
module:

module Admin
class UserController < ActionController::Base

end
end

Routes are then smart enough to figure this out. For example the route,
/:controller/:action, would map the URL ‘/admin/user/add’ to the
Admin::UserController#add method.

Hope this helps,

Maurice


#6

On 5/12/06, szymek removed_email_address@domain.invalid wrote:

This way you won’t have to mess with routes at all.
Indeed, this is the best solution. I do:

ruby script/generate controller admin/users add

And then I have an Admin namespace, where I can put the various admin/
controllers. This is indeed hadnled automatically (and very well) by
Rails’ default routing settings. And since an Admin namespace is all I
needed - both for request-handling and code-organization (in a neat,
seperate subdirectory - it’s enough to take care of the task I
presented.

However, it was good to learn about the available routes.rb methods.
If at any point in the future I need a hierarchy beyond two levels
deep after the controller (all I needed now was the regular 3-level
/:controller/:action/:id inside an Admin namespace), I can simply add
it to routes.rb thus:

ActionController::Routing::Routes.draw do |map|

map.connect ‘:controller/:action/:group/:id’

end

And then things like:

link_to(‘Add user 21 to the “viewers” group’, ‘group’ => ‘viewers’, ‘id’
=> 21)

would work as expected. (Note: the above link_to call would work well
only inside the ‘admin/users’ namespace [which is reasonable for this
use-case], the full parameters for getting the same URI from anywhere
in the application is:

link_to(‘Add user 21 to the “viewers” group’, :controller =>
‘admin/users’, :action => ‘add’, ‘group’ => ‘viewers’, ‘id’ => 21)
)


-Alder