Namespace routing rails nightmare
I am in the process of still learning Rails 3 but routes are driving me crazy. I am trying to use a namespace to separate an administration section of the site. Problem is that some things in the namespace simply don't work and also route to the wrong place. For example using rails generated routes by specifying a resource the view points to the wrong route when passed an object so the edit form won't work.
Links with link_to don't work either even when the route does exist it says it doesn't. Firstly here is the namespaced routes output from rake routes.
namespace :admin do
resources :users
end
admin_users GET /admin/users(.:format) {:action=>"index", :controller=>"admin/users"}
POST /admin/users(.:format) {:action=>"create", :controller=>"admin/users"}
new_admin_user GET /admin/users/new(.:format) {:action=>"new", :controller=>"admin/users"}
edit_admin_user GET /admin/users/:id/edit(.:format) {:action=>"edit", :controller=>"admin/users"}
admin_user PUT /admin/users/:id(.:format) {:action=>"update", :controller=>"admin/users"}
DELETE /admin/users/:id(.:format) {:action=>"destroy", :controller=>"admin/users"}
Controller:
class Admin::UsersController < ApplicationController
def index
@users = User.all
end
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def edit
@user = User.find(params[:id])
end
def create
@user = User.new(params[:user])
if @user.save
redirect_to(@user, :notice => 'User was successfully created.')
else
render :action => "new"
end
end
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:开发者_开发百科user])
redirect_to(admin_users_path, :notice => 'User was successfully updated.')
else
render :action => "edit"
end
end
def destroy
@user = User.find(params[:id])
@user.destroy
redirect_to(admin_users_path)
end
end
Example view: index.html.erb listing all users
<h1>Listing users</h1>
<table>
<% for user in @users %>
<tr>
<td><%= user.id %></td>
<td><%= user.username %></td>
<td><%= user.email %></td>
<td><%= link_to 'Show', @user %></td>
<td><%= link_to 'Edit', edit_admin_user_path(user) %></td>
<td><%= link_to 'Destroy', admin_user_path, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New User', new_admin_user_path %>
Using the edit view is also having a problem. The edit form should point to the update route but does not. Instead it points to the edit route (basically itself) when only being passed a User object. From what I have been reading using an object in forms is the recommended way but this cant be a good thing if it does not work.
I get this error on listing all users page.
No route matches {:action=>"update", :controller=>"admin/users"}
Extracted source (around line #17):
17: <td><%= link_to 'Destroy', admin_user_path, :confirm => 'Are you sure?', :method => :delete %></td>
I am so trying to persevere but this is driving me loopy. FYI: Yes I know there are authentication frameworks out there but I am trying to make one from scratch. This is a learning experience and as such just using gems and plugins willy nilly is not the way to go in my opinion.
Thank you Onyth
You're missing the id in the delete link
Try with
<td><%= link_to 'Destroy', admin_user_path(user), :confirm => 'Are you sure?', :method => :delete %></td>
(changed admin_user_path to admin_user_path(user) as the link)
If you do a rake routes you would see something like this:
admin_users GET /admin/users(.:format) {:controller=>"admin/users", :action=>"index"}
POST /admin/users(.:format) {:controller=>"admin/users", :action=>"create"}
new_admin_user GET /admin/users/new(.:format) {:controller=>"admin/users", :action=>"new"}
edit_admin_user GET /admin/users/:id/edit(.:format) {:controller=>"admin/users", :action=>"edit"}
admin_user GET /admin/users/:id(.:format) {:controller=>"admin/users", :action=>"show"}
PUT /admin/users/:id(.:format) {:controller=>"admin/users", :action=>"update"}
DELETE /admin/users/:id(.:format) {:controller=>"admin/users", :action=>"destroy"}
admin_pages GET /admin/pages(.:format) {:controller=>"admin/pages", :action=>"index"}
POST /admin/pages(.:format) {:controller=>"admin/pages", :action=>"create"}
new_admin_page GET /admin/pages/new(.:format) {:controller=>"admin/pages", :action=>"new"}
edit_admin_page GET /admin/pages/:id/edit(.:format) {:controller=>"admin/pages", :action=>"edit"}
admin_page GET /admin/pages/:id(.:format) {:controller=>"admin/pages", :action=>"show"}
PUT /admin/pages/:id(.:format) {:controller=>"admin/pages", :action=>"update"}
DELETE /admin/pages/:id(.:format) {:controller=>"admin/pages", :action=>"destroy"}
So you can derive
admin_user_path
which would be the same as
user_path
Then you would pass the @user in admin_user_path like so:
admin_user_path(@user)
The :method should then call the destroy method instead of going to the show method automatically! :)
To get the form_for working, I found the following resource: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for
Under the form_for section, they explain namespace routing with form_for as:
For namespaced routes, like admin_post_url:
<%= form_for([:admin, @post]) do |f| %>
...
<% end %>
For information regarding rake routes check out: http://guides.rubyonrails.org/command_line.html#rake-is-ruby-make then under section 2.4.9 Miscellaneous Tasks they explain rake --tasks shows you various rake commands that you can use and rake routes shows you route paths available.
Hope this helps!
精彩评论