Rails routes, problem with custom :action not being recognized, always 'show'
I'm trying to 'manage' users, instead of 'new' and 'show' users via actions. The problem is somewhere in routes I suspect, as my link '/users/manage' is being received as an id parameter to 'show' action:
Terminal log of process:
Processing UsersController#show (for 127.0.0.1 at 2010-06-28 00:31:45) [GET]
Parameters: {"id"=>"manage"}
ActionController::UnknownAction (No action responded to show. Actions: create, destroy, index, manage, and update):
Here are some code snippets of relevant parts:
users/index.html.erb (the link created to go to the manage section, i.e. '/users/manage'):
<%= link_to('New User', :action => 'manage') %>
users_controller.rb (supposed to be receiving 'manage' action, but gets 'show' fr om above call:
def index
@users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @users }
end
end
def manage
@users = User.all
@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
Ruby/rails sees '/users/manage' as a ':controller/:action/:id' i.e. 'users/show/1'.
When using '/users/manage/1' to edit a single user, the proper :action (as 'manage') is loaded via the UsersController 'manage' function, and everything is displayed to edit from the manage.html.erb file. UsersController sees 'manage' and not 'show', correctly, int his case, but only because of the :id being passed making the ':controller/:action/:id' route kick in and work.
'users/manage', :controller/:action seems to be the problem, not recognizing 'manage' as a valid :action alone, instead sending is as an :id in 'show'...
routes.rb:
ActionController::Routing::Routes.draw do |map|
map.resources :users
map.resources :categories
map.resources :posts
map.connect ':controller/:action'
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
Can someone please help me resolve this?
Why is the 'show' action being automatically undertaken? Can I force 'users' and 'manage' in routes to be recognized in the controller as 'manage' and not as 'show'?
Thanks for the help people :)
Peace.
EDIT rake routes
$ rake routes
(in /home/krnel/sites/rails_projects/simple_blog)
users GET /users(.:format) {:action=>"index", :controller=>"users"}
POST /users(.:format) {:action=>"create", :controller=>"users"}
new_user GET /users/new(.:format) {:action=>"new", :controller=>"users"}
edit_user GET /users/:id/edit(.:format) {:action=>"edit", :controller=>"users"}
user GET /users/:id(.:format) {:action=>"show", :controller=>"users"}
PUT /users/:id(.:format) {:action=>"update", :controller=>"users"}
DELETE /users/:id(.:format) {:action=>"destroy", :controller=>"users"}
categories GET /categories(.:format) {:action=>"index", :controller=>"categories"}
POST /categories(.:format) {:action=>"create", :controller=>"categories"}
new_category GET /categories/new(.:format) {:action=>"new", :controller=>"categories"}
edit_category GET /categories/:id/edit(.:format) {:action=>"edit", :controller=>"categories"}
category GET /categories/:id(.:format) {:action=>"show", :controller=>"categories"}
PUT /categories/:id(.:format) {:action=>"update", :controller=>"categories"}
DELETE /categories/:id(.:format) {:action=>"destroy", :controller=>"categories"}
posts GET /posts(.:format) {:action=>"index", :controller=>"posts"}
POST /posts(.:format) {:action=>"create", :controller=>"posts"}
new_post GET /posts/new(.:format) {:action=>"new", :controller=>"posts"}
edit_post GET /posts/:id/edit(.:format) {:action=>"edit", :controller=>"posts"}
post GET /posts/:id(.:format) {:action=>"show", :controller=>"posts"}
PUT /posts/:id(.:format) {:action=>"update", :controller=>"posts"}
DELETE /posts/:id(.:format) {:action=>"destroy", :controller=>"posts"}
manage_users GET /users/manage(.:format) {:action=>"manage", :controller=>"users"}
GET /users(.:format)开发者_如何转开发 {:action=>"index", :controller=>"users"}
POST /users(.:format) {:action=>"create", :controller=>"users"}
GET /users/new(.:format) {:action=>"new", :controller=>"users"}
GET /users/:id/edit(.:format) {:action=>"edit", :controller=>"users"}
GET /users/:id(.:format) {:action=>"show", :controller=>"users"}
PUT /users/:id(.:format) {:action=>"update", :controller=>"users"}
DELETE /users/:id(.:format) {:action=>"destroy", :controller=>"users"}
/:controller/:action/:id
/:controller/:action/:id(.:format)
You're never actually mapping a 'manage' action specifically. You are however mapping /users, /users/:id, /users/:id/edit and some more (post, put, delete) routes by doing map.resources :users. Check your rake routes
to find out what exactly you've mapped.
As per your question, in your case you can add a route to user resources as follows:
map.resources :users, :collection => {:manage => :get}
This will add /users/manage GET route for your action. You can add :member(s) or :collection(s) this way. The difference is that member will be expecting an :id to be provided, while collection won't.
Read more in the rails routing guide: http://guides.rubyonrails.org/routing.html
The right way
What you probably want to do is create an Admin namespace for managing users. Then your users will be accessible through /admin/users, /admin/users/:id, /admin/users/:id/edit, etc. This way you can separate the interface in which you're managing the users from the one where users are editing their own profiles. This is a better practice, because this way you don't need to come up with custom routes like /users/manage. It will provide a CRUD area for administration, unrelated to CRUD area for users themselves.
You can add routes like below for other GET type actions of a controller -
resources :users do
collection do
get 'manage'
end
end
If you want to rename your routes, use :path_names hash in your routes like this.
map.resources :photos, :path_names => { :new => 'make', :edit => 'change' }
This would cause the routing to recognize URLs such as
/photos/make /photos/1/change
The actual action names aren’t changed by this option; the two URLs shown would still route to the new and edit actions.
See this guide for more info: http://guides.rubyonrails.org/routing.html
I know it is super late and 2020 but if you by accident duplicate the routes in routes.rb it will give you this weird situation. For example: #routes.rb
resources :users
...(bunch of other routes declaration later)
resources users do
collection do
get :manage
end
This will cause that when you try to access GET /users/manage it will go to the :show action. I saw in the screenshot you posted that you have the /users routes listed twice. That's an indicator. Find the simple resources :users
and delete it and leave the one that has more stuff in it since it's the version you need.
精彩评论