views:

225

answers:

3

Say if I have a controller, profile, which has just two actions. The first one is list, which will just show the list of names. I want these names to be links which will then take you to a page that shows the full profile. So I need a second action, view, which can then bed fed a parameter to indicate which profile to view.

For example: I would access /profile/list, then if I want to view John's profile, I will click on his name which should take me to /profile/view/john. My view action will read the john parameter and then make the appropriate database queries.

What changes do I have to make to routes.rb for this to happen? Cheers.

A: 

If the model is "user" you have to override the to_param method. This will allow you to return the "id-name" of the user instead of the "id". (ex: /profile/view/23-john)

I know, it's not exactly what you asked for but this should be a easy solution.

class User < ActiveRecord::Base
  def to_param
    "#{id}-#{name.gsub(/\W/, '-').downcase}"
  end
end

And just add a simple resource declaration to the routing configuration:

map.resources :users
baijiu
A: 

I'd rather use the default :controller/:action/:id route to protect against cases where there are 2 John's in the list.

To have a custom route like you mentioned edit Routes.rb to include a new one

map.connect ':controller/:action/:user_name'

Now a request like profile/view/john should reach you as

@params = {:controller => "profile", :action=> "view", :user_name => "john"}

Use the params[:user_name] value to locate and display the relevant record in the controller's view action. You can also want to setup some requirements on the :user_name part of the url, e.g. it has to match /SomeRegexpToValidateNames/

map.connect ':controller/:action/:user_name',
   :requirements => {:user_name => /\w+/}
Gishu
How do I change map.connect ':controller/:action/:user_name' so that I hardcode profile/view. Because I don't care about other things such as /one/two/three.
alamodey
/one/two/three would attempt to call the action called two on one_controller. Rails should not be able to find this and handle this with a 'generic page not found'. If you really want to hardcode this you can specify more stringent :requirements => {:controller=>/profile/, :action=>/view/,..}
Gishu
A: 

if you want to identify profiles by name, as "/profile/view/john" you can use the permalink_fu plugin

http://www.seoonrails.com/even-better-looking-urls-with-permalink_fu

which will keep you out of trouble when there's name duplication...

Maximiliano Guzman