Routing Problem?

I started out with a normal scaffold for the USERS table. I changed
the index view to be list.html.erb but the url: ‘/users/list’ returns
an ‘unknown action’ error. ‘/users/list/:id’ also returns an ‘unknown
action’ error. I’ve also merged both the edit and new views into the
manage.html.erb which duplicates the list view except with a form on
the right side. the url ‘/users/manage’ returns an ‘unknown action’
error but ‘/users/manage/:id’ brings me to the manage page with the
edit form.

in my routes.rb, it reads:
map.resources :users

The update an delete actions work but they don’t route me to the right
url. the new action does not work. can anyone help? I’ve pasted my
controller and views below.

USERS CONTOLLER
class UsersController < ApplicationController

layout ‘staff’

def index
list
render :action => ‘list’
end

GET /users

GET /users.xml

def list
@users = User.find(:all)

respond_to do |format|

format.html # index.html.erb

format.xml { render :xml => @users }

end

end

GET /users/new

GET /users/new.xml

def manage
list
@user = User.find(params[:id]) if params[:id]
@user = User.new if @user.nil?

respond_to do |format|

format.html # new.html.erb

format.xml { render :xml => @user }

end

end

POST /users

POST /users.xml

def create
@user = User.new(params[:user])

respond_to do |format|
  if @user.save
    flash[:notice] = 'User was successfully created.'
    format.html { redirect_to(users_url) }
    format.xml  { render :xml => @user, :status

=> :created, :location => @user }
else
format.html { render(:action => “manage”) }
format.xml { render :xml => @user.errors, :status
=> :unprocessable_entity }
end
end
end

PUT /users/1

PUT /users/1.xml

def update
@user = User.find(params[:id])

respond_to do |format|
  if @user.update_attributes(params[:user])
    flash[:notice] = 'User was successfully updated.'
    format.html { redirect_to(users_url) }
    format.xml  { head :ok }
  else
    format.html { render(:action => 'manage') }
    format.xml  { render :xml => @user.errors, :status

=> :unprocessable_entity }
end
end
end

DELETE /users/1

DELETE /users/1.xml

def destroy
@user = User.find(params[:id])
@user.destroy

respond_to do |format|
  flash[:notice] = 'User was successfully deleted.'
  format.html { redirect_to(:action => 'list') }
  format.xml  { head :ok }
end

end

end

LIST VIEW
<% @page_title = ‘Current Users’ -%>

<%= content_tag(‘p’, link_to(’« Back to Menu’, :controller =>
‘staff’, :action => ‘menu’)) %>

<%= render(:partial => 'listing') -%>
Please select a user on the left or create a new user. <%= link_to('New user', :action => 'manage') -%>

MANAGE VIEW
<% @page_title = ‘Current Users’ -%>

<%= content_tag(‘p’, link_to(’« Back to Menu’, :controller =>
‘staff’, :action => ‘menu’)) %>

<%= render(:partial => 'listing') -%>
<% if params[:id].blank? %>

New user

<% form_for(@user) do |f| -%>
  <%= render(:partial => 'form') -%>
  <p class= 'user_submit'><%= submit_tag "Create" -%></p>
<% end -%>

<% else -%>

Editing user

<% form_for(@user) do |f| -%>
  <%= render(:partial => 'form')%>
  <p class= 'user_submit'><%= submit_tag "Update" -%></p>
<% end -%>

<p class= 'user_submit'><%= link_to('Delete User', { :action =>

‘destroy’,
:id => @user }, :confirm => ‘Are you sure you want to permanently
delete this user?’,
:method => :delete) -%>

<% end -%>

<%= link_to(‘Cancel’, :action => ‘list’) %>

_LISTING PARTIAL

<% for user in @users -%> '> <% end %>
First Name Last Name Username User Level
<%= h(user.first_name) -%> <%= h(user.last_name) -%> <%= h(user.username) -%> <%= h(user.user_level) -%> <%= link_to('Edit', :action => 'manage', :id => user) -%>

_FORM PARTIAL
<%= error_messages_for(:user) -%>

Username <%= text_field(:user, :username) -%>
Hashed Password <%= text_field(:user, :hashed_password) -%>
First Name <%= text_field(:user, :first_name) -%>
Last Name <%= text_field(:user, :last_name) -%>
Email <%= text_field(:user, :email) -%>
Display Name <%= text_field(:user, :display_name) -%>
User Level <%= select(:user, :user_level, [0,1,2,3,4,9]) -%>

Check the output of “rake routes” to see which routes are recognized.
When you are sure your URLs follow the expected URLs, check that your
actions correspond. Keep an eye on the log file to see what’s going
on.

Christian

rename the action in your controller

Please read

to gain a better understanding of restful routing.

I also don’t recommend merging the new action with the edit action
because you may run into problems later on

Ryan B.
Freelancer
Skype: radarlistener
MSN & Gtalk: [email protected]

chris wrote:

I started out with a normal scaffold for the USERS table. I changed
the index view to be list.html.erb but the url: ‘/users/list’ returns
an ‘unknown action’ error. ‘/users/list/:id’ also returns an ‘unknown
action’ error. I’ve also merged both the edit and new views into the
manage.html.erb which duplicates the list view except with a form on
the right side. the url ‘/users/manage’ returns an ‘unknown action’
error but ‘/users/manage/:id’ brings me to the manage page with the
edit form.

Simply adding the method in the controller doesn’t give you the route,
nor does changing the name of the method in the controller. The reason
‘/users/manage/:id’ works is because it gets scooped up by your default
route ‘/:controller/:action/:id’.

Take a look at the :member and :collection options to map.resources.
Then can be used as such:

to add a method to an object of class User

this will give you /users/:id/change_name

map.resources :users, :member => {:change_name => [:get, :post]}

to add a method to the class itself

this will give you /users/active

map.resources :users, :collection => {:active => :get}

You may also be interested in the :path_names option, to change the
names of the typical routes.

to change “edit” to “manage”

map.resources :users, :path_names => { :new => ‘manage’ }

I’m not sure what would happen if you mapped two methods to the same
name:

may or may not work as you’d expect

map.resources :users, :path_names => { :new => ‘manage’, :edit =>
‘manage’ }

Reference:
http://api.rubyonrails.org/classes/ActionController/Resources.html

Hope that helps.

Cheers,
Darrik

We’ll i’ve read into RESTful routes and your other suggestions yet
still can’t seem to fix the problem. here’s the output from RAKE
ROUTES:

users GET /users {:controller=>“users”, :action=>“index”}
formatted_users GET /users.:format
{:controller=>“users”, :action=>“index”}
POST /users {:controller=>“users”, :action=>“create”}
POST /users.:format {:controller=>“users”, :action=>“create”}
new_user GET /users/manage {:controller=>“users”, :action=>“new”}
formatted_new_user GET /users/manage.:format
{:controller=>“users”, :action=>“new”}
edit_user GET /users/:id/manage
{:controller=>“users”, :action=>“edit”}
formatted_edit_user GET /users/:id/manage.:format
{:controller=>“users”, :action=>“edit”}
user GET /users/:id {:controller=>“users”, :action=>“show”}
formatted_user GET /users/:id.:format
{:controller=>“users”, :action=>“show”}
PUT /users/:id {:controller=>“users”, :action=>“update”}
PUT /users/:id.:format {:controller=>“users”, :action=>“update”}
DELETE /users/:id {:controller=>“users”, :action=>“destroy”}
DELETE /users/:id.:format {:controller=>“users”, :action=>“destroy”}
categories GET /categories
{:controller=>“categories”, :action=>“index”}
formatted_categories GET /categories.:format
{:controller=>“categories”, :action=>“index”}
POST /categories {:controller=>“categories”, :action=>“create”}
POST /categories.:format
{:controller=>“categories”, :action=>“create”}
new_category GET /categories/new
{:controller=>“categories”, :action=>“new”}
formatted_new_category GET /categories/new.:format
{:controller=>“categories”, :action=>“new”}
edit_category GET /categories/:id/edit
{:controller=>“categories”, :action=>“edit”}
formatted_edit_category GET /categories/:id/edit.:format
{:controller=>“categories”, :action=>“edit”}
category GET /categories/:id
{:controller=>“categories”, :action=>“show”}
formatted_category GET /categories/:id.:format
{:controller=>“categories”, :action=>“show”}
PUT /categories/:id {:controller=>“categories”, :action=>“update”}
PUT /categories/:id.:format
{:controller=>“categories”, :action=>“update”}
DELETE /categories/:id
{:controller=>“categories”, :action=>“destroy”}
DELETE /categories/:id.:format
{:controller=>“categories”, :action=>“destroy”}
posts GET /posts {:controller=>“posts”, :action=>“index”}
formatted_posts GET /posts.:format
{:controller=>“posts”, :action=>“index”}
POST /posts {:controller=>“posts”, :action=>“create”}
POST /posts.:format {:controller=>“posts”, :action=>“create”}
new_post GET /posts/new {:controller=>“posts”, :action=>“new”}
formatted_new_post GET /posts/new.:format
{:controller=>“posts”, :action=>“new”}
edit_post GET /posts/:id/edit {:controller=>“posts”, :action=>“edit”}
formatted_edit_post GET /posts/:id/edit.:format
{:controller=>“posts”, :action=>“edit”}
post GET /posts/:id {:controller=>“posts”, :action=>“show”}
formatted_post GET /posts/:id.:format
{:controller=>“posts”, :action=>“show”}
PUT /posts/:id {:controller=>“posts”, :action=>“update”}
PUT /posts/:id.:format {:controller=>“posts”, :action=>“update”}
DELETE /posts/:id {:controller=>“posts”, :action=>“destroy”}
DELETE /posts/:id.:format {:controller=>“posts”, :action=>“destroy”}
/:controller/:action/:id.:format
/:controller/:action/:id

Sorry that its difficult to read, google’s text editor doesn’t really
offer much. I also tried adding the following into my ROUTES.RB:

map.resources :users, :path_names => { :new => ‘manage’, :edit =>
‘manage’ }, :collection => {:list => :get, :manage =>
[:post, :put, :delete]}

This adding the following 4 lines to my RAKE ROUTES:

manage_users POSTPUTDELETE /users/manage
{:controller=>“users”, :action=>“manage”}
formatted_manage_users POSTPUTDELETE /users/manage.:format
{:controller=>“users”, :action=>“manage”}
list_users GET /users/list
{:controller=>“users”, :action=>“list”}
formatted_list_users GET /users/list.:format
{:controller=>“users”, :action=>“list”}

It looks right to me but when i redirect to the url => ‘users/list’ or
‘users/manage’, it sends ‘list’ or ‘manage’ as the :id and it gives me
an unknown action error. This means my new, create, update, destroy
methods all don’t work.

please look at the first post for my CONTROLLER and VIEW code.

Thanks for the replies guys, especially you Darrik. I actually did
have a look at the options to map.resources but was a little
overwhelmed. The tutorial I’ve been trying to complete merges the NEW
and EDIT actions to show how its possible to put all those actions
into a single method but in doing so, it just royally screws with the
default routes. I’m going to play around with the options as you
suggest and I’ll let you know how I do in the next few days. thanks.

We’ll i’ve read into RESTful routes and your other suggestions yet
still can’t seem to fix the problem. here’s the output from RAKE
ROUTES:

users GET /users {:controller=>“users”, :action=>“index”}
formatted_users GET /users.:format
{:controller=>“users”, :action=>“index”}
POST /users {:controller=>“users”, :action=>“create”}
POST /users.:format {:controller=>“users”, :action=>“create”}
new_user GET /users/manage {:controller=>“users”, :action=>“new”}
formatted_new_user GET /users/manage.:format
{:controller=>“users”, :action=>“new”}
edit_user GET /users/:id/manage
{:controller=>“users”, :action=>“edit”}
formatted_edit_user GET /users/:id/manage.:format
{:controller=>“users”, :action=>“edit”}
user GET /users/:id {:controller=>“users”, :action=>“show”}
formatted_user GET /users/:id.:format
{:controller=>“users”, :action=>“show”}
PUT /users/:id {:controller=>“users”, :action=>“update”}
PUT /users/:id.:format {:controller=>“users”, :action=>“update”}
DELETE /users/:id {:controller=>“users”, :action=>“destroy”}
DELETE /users/:id.:format {:controller=>“users”, :action=>“destroy”}
categories GET /categories
{:controller=>“categories”, :action=>“index”}
formatted_categories GET /categories.:format
{:controller=>“categories”, :action=>“index”}
POST /categories {:controller=>“categories”, :action=>“create”}
POST /categories.:format
{:controller=>“categories”, :action=>“create”}
new_category GET /categories/new
{:controller=>“categories”, :action=>“new”}
formatted_new_category GET /categories/new.:format
{:controller=>“categories”, :action=>“new”}
edit_category GET /categories/:id/edit
{:controller=>“categories”, :action=>“edit”}
formatted_edit_category GET /categories/:id/edit.:format
{:controller=>“categories”, :action=>“edit”}
category GET /categories/:id
{:controller=>“categories”, :action=>“show”}
formatted_category GET /categories/:id.:format
{:controller=>“categories”, :action=>“show”}
PUT /categories/:id {:controller=>“categories”, :action=>“update”}
PUT /categories/:id.:format
{:controller=>“categories”, :action=>“update”}
DELETE /categories/:id
{:controller=>“categories”, :action=>“destroy”}
DELETE /categories/:id.:format
{:controller=>“categories”, :action=>“destroy”}
posts GET /posts {:controller=>“posts”, :action=>“index”}
formatted_posts GET /posts.:format
{:controller=>“posts”, :action=>“index”}
POST /posts {:controller=>“posts”, :action=>“create”}
POST /posts.:format {:controller=>“posts”, :action=>“create”}
new_post GET /posts/new {:controller=>“posts”, :action=>“new”}
formatted_new_post GET /posts/new.:format
{:controller=>“posts”, :action=>“new”}
edit_post GET /posts/:id/edit {:controller=>“posts”, :action=>“edit”}
formatted_edit_post GET /posts/:id/edit.:format
{:controller=>“posts”, :action=>“edit”}
post GET /posts/:id {:controller=>“posts”, :action=>“show”}
formatted_post GET /posts/:id.:format
{:controller=>“posts”, :action=>“show”}
PUT /posts/:id {:controller=>“posts”, :action=>“update”}
PUT /posts/:id.:format {:controller=>“posts”, :action=>“update”}
DELETE /posts/:id {:controller=>“posts”, :action=>“destroy”}
DELETE /posts/:id.:format {:controller=>“posts”, :action=>“destroy”}
/:controller/:action/:id.:format
/:controller/:action/:id

Sorry that its difficult to read, google’s text editor doesn’t really
offer much. I also tried adding the following into my ROUTES.RB after
|map.resources :users| which was already in there:

:path_names => { :new => ‘manage’, :edit => ‘manage’ }, :collection
=> {:list => :get, :manage => [:post, :put, :delete]}

This adding the following 4 lines to my RAKE ROUTES:

manage_users POSTPUTDELETE /users/manage
{:controller=>“users”, :action=>“manage”}
formatted_manage_users POSTPUTDELETE /users/manage.:format
{:controller=>“users”, :action=>“manage”}
list_users GET /users/list
{:controller=>“users”, :action=>“list”}
formatted_list_users GET /users/list.:format
{:controller=>“users”, :action=>“list”}

It looks right to me but when i redirect to the url => ‘users/list’ or
‘users/manage’, it sends ‘list’ or ‘manage’ as the :id and it gives me
an unknown action error. This means my new, create, update, destroy
methods all don’t work.

please look at the first post for my CONTROLLER and VIEW code.

chris wrote:

formatted_new_user GET /users/manage.:format
DELETE /users/:id {:controller=>“users”, :action=>“destroy”}
formatted_new_category GET /categories/new.:format
PUT /categories/:id.:format
new_post GET /posts/new {:controller=>“posts”, :action=>“new”}
DELETE /posts/:id {:controller=>“posts”, :action=>“destroy”}

overwhelmed. The tutorial I’ve been trying to complete merges the NEW

an ‘unknown action’ error. ‘/users/list/:id’ also returns an 'unknown
Then can be used as such:
I’m not sure what would happen if you mapped two methods to the same name:

may or may not work as you’d expect

map.resources :users, :path_names => { :new => ‘manage’, :edit =>
‘manage’ }
Reference:http://api.rubyonrails.org/classes/ActionController/Resources.html
Hope that helps.
Cheers,
Darrik

Your controller doesn’t have a method called ‘list’ or ‘manage’.

Also of note, if you expect the manage method to manipulate an
individual object of the User class, you should add it as :member, not
:collection. Collection (as the name implies) defines actions that
operate on the entire collection (list, index, etc), whereas member
defines actions that operate on a single member (also as the name
implies). The key distinction is that the :collection option to mapping
a User resource will give you a route like /users/:action, whereas the
:member option will give you a route like /users/:id/:action, in both
cases where :action is whatever you specify.

Hope that helps.
Darrik


Darrik Mazey
Developer
DMT Programming, LLC.
P.O. Box 91
Torrington, CT 06790
office: 330.983.9941
fax: 330.983.9942
mobile: 330.808.2025
[email protected]

To obtain my public key, send an email to
[email protected].

I actually do have a method called ‘list’ and ‘manage’ in my
controller so i’m not sure why you say I don’t.

I’ve actually updated my Users Controller since the first post. it now
looks like this (I’ve CAPITALIZED the LIST and MANAGE methods:

class UsersController < ApplicationController

layout ‘staff’

def index
list
render :action => ‘list’
end

GET /users

GET /users.xml

def LIST
@users = User.find(:all)

respond_to do |format|

format.html # index.html.erb

format.xml { render :xml => @users }

end

end

GET /users/new

GET /users/new.xml

def MANAGE
list
if request.get? && params[:id].blank? #new
@user = User.new
elsif request.post? && params[:id].blank? #create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
flash[:notice] = ‘The user was successfully created.’
format.html { redirect_to(:action => ‘list’) }
format.xml { render :xml => @user, :status
=> :created, :location => @user }
else
format.html { render(:action => “manage”) }
format.xml { render :xml => @user.errors, :status
=> :unprocessable_entity }
end
end

elsif request.get? && !params[:id].blank? #edit
  @user = User.find(params[:id])
else request.post? && !params[:id].blank? #update or delete
  @user = User.find(params[:id])
  if params[:commit] == 'Update'
    respond_to do |format|
      if @user.update_attributes(params[:user])
        flash[:notice] = 'The user was successfully updated.'
        format.html { redirect_to(:action => 'list') }
        format.xml  { head :ok }
      else
        format.html { render(:action => 'manage') }
        format.xml  { render :xml => @user.errors, :status

=> :unprocessable_entity }
end
end
else #action should delete
@user = User.find(params[:id])
@user.destroy
respond_to do |format|
flash[:notice] = ‘The user was successfully deleted.’
format.html { redirect_to(:action => ‘list’) }
format.xml { head :ok }
end
end
end
end

end

I’ve made some very slight changes to my view to deal with the fact
that I no longer have a ‘create’ ‘update’ or ‘destroy’ method
anymore. As you can see, I’ve rolled all those methods into a single
method, ‘manage’.

LIST VIEW
<% @page_title = ‘Current Users’ -%>

<%= content_tag(‘p’, link_to(’« Back to Menu’, :controller =>
‘staff’, :action => ‘menu’)) %>

<%= render(:partial => 'listing') -%>
Please select a user on the left or create a new user. <%= link_to('New user', :action => 'manage') -%>

MANAGE VIEW
<% @page_title = ‘Current Users’ -%>

<%= content_tag(‘p’, link_to(’« Back to Menu’, :controller =>
‘staff’, :action => ‘menu’)) %>

<%= render(:partial => 'listing') -%>
<% if params[:id].blank? %>

New user

<%# form_tag(:action => 'manage') do -%>
<% form_for(@user) do -%>
  <%= render(:partial => 'form') -%>
  <p class= 'user_submit'><%= submit_tag "Create" -%></p>
<% end -%>

<% else -%>

Editing user

<%# form_tag(:action => 'manage', :id => @user) do -%>
<% form_for(@user) do -%>
  <%= render(:partial => 'form')%>
  <p class= 'user_submit'><%= submit_tag "Update" -%></p>
<% end -%>

<p class= 'user_submit'><%= link_to('Delete User', { :action =>

‘destroy’,
:id => @user }, :confirm => ‘Are you sure you want to permanently
delete this user?’,
:method => :delete) -%>

<% end -%>

<%= link_to(‘Cancel’, :action => ‘list’) %>

_LISTING PARTIAL

<% for user in @users -%> '> <% end %>
First Name Last Name Username User Level
<%= h(user.first_name) -%> <%= h(user.last_name) -%> <%= h(user.username) -%> <%= h(user.user_level) -%> <%= link_to('Edit', :action => 'manage', :id => user) -%>

_FORM PARTIAL

<%= error_messages_for(:user) -%>

Username <%= text_field(:user, :username) -%>
Hashed Password <%= text_field(:user, :hashed_password) -%>
First Name <%= text_field(:user, :first_name) -%>
Last Name <%= text_field(:user, :last_name) -%>
Email <%= text_field(:user, :email) -%>
Display Name <%= text_field(:user, :display_name) -%>
User Level <%= select(:user, :user_level, (0..9).to_a.reverse) -%>

I also tried to configure my ROUTES.RB as you’ve suggested, using
the :member option instead of the :collection for the ‘manage’ action
as such:

ActionController::Routing::Routes.draw do |map|
map.resources :users, :path_names => { :new => ‘manage’, :edit =>
‘manage’ },
:collection => {:list => :get}, :member => {:manage =>
[:post, :put, :delete]}

map.resources :categories

map.resources :posts

map.connect ‘:controller/:action/:id.:format’
map.connect ‘:controller/:action/:id’
end

Now, when I goto the url: ‘/users/manage’ (the url for creating a new
user object) and ‘/users/:id/manage’ (the url for editing an existing
user object) it still gives me the unknown action error. Instead of
sending ‘manage’ as the :id (which is what it did before I added
the :path_names, :collection, :member options in my routes.rb code),
it sends ‘new’ and ‘edit’ as the :action where instead it should be
sending ‘manage’ as the action or so I think.

Thanks again.