Devise/ Delete user Error - ruby-on-rails

I am creating a form for an admin to go in and list, edit and delete users. I have tried many different variations for deleting a user and nothing works. I am wondering if it is because I need to use devise_for :users and resources :users in my routes.rb. This is because I have uploads/attachments linked to users. But here is my link
<%= link_to 'Delete',user, :method => 'delete', :confirm => 'Are you sure?' %>
And my routes.rb
# devise_for :users
devise_for :users do
get "/users/sign_out" => "devise/sessions#destroy", :as => :destroy_user_session
end
resources :users do
resources :attachments
end
The error I am receiving is The action 'destroy' could not be found for UsersController.
But my users controller has
def destroy
#user = User.find(params[:id]).destroy
redirect_to admin_index, :flash => { :success => 'User was successfully deleted.' }
end

If you are not using ajax for the requests, the problem is taht you ar using a link_to
In order to send the :method => 'delete' you have to use a button, jus like this:
<%= button_to 'Delete', user, :method => 'delete', :confirm => 'Are you sure?' %>
Because destructive action must be performed with a form submission:
http://www.w3.org/2001/tag/doc/whenToUseGet.html#checklist

Related

Resources delete method not working with Devise

I am using devise gem for authentication. For the admin user I am trying to create a page where he will see the list of all users and will be able to delete them. Because devise does not provide action for delete I created a controller where I created destroy action.
controller:
def destroy
User.find(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to("/devise")
end
The view is simple, it just lists all users and posts a delete link next to them.
<% #users.each do |user| %>
<%= user.email %> <%= link_to 'Delete', :controller => :devise, :action => :destroy, :id => (user[:id]), method: :delete, data: { confirm: "Are you sure you want to delete this user permanently?" } %>
<% end %>
Up until this point it works - the page displays all users and the delete link too. However, when I try to delete random users it just opens them in new window instead of deleting them.
My routes are as follows:
Rails.application.routes.draw do
devise_for :admins
devise_for :users
resources :devise
resources :centres
resources :users
#match '/users/:id', :to => 'devise#show', :as => :user, :via => :get
match '/users/:id', :to => 'devise#destroy', :as => :destroy_user, :via => :delete
root 'welcome#index'
get '/index', to: 'welcome#index'
get '/about', to: 'welcome#about'
get '/help', to: 'welcome#help'
end
I need to make the delete function work. Thank you.
This is the solution for the question I posted:
controlled:
def destroy
User.find(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to("/users")
end
view:
<%= link_to "delete", user, method: :delete,
data: { confirm: "Are you sure you want to permanently delete this user?" } %>
route:
match '/users/:id', :to => 'users#destroy', :as => :destroy_user, :via => :delete
As far as i know, device doesn't handle destroy action. You should create a custom controller and provide a destroy action. In my case, i create a users_controller
users_controller:
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :ok }
end
end
html.erb:
<%= link_to 'Delete', user, method: :delete, data: { confirm: 'Are you sure?' } %>
routes.rb:
match '/users/:id', :to => 'users#destroy', :as => :destroy_user, :via => :delete

The link for deleting item returns undefined method

This is the relevant part of the routes:
resources :photos, :path => '', :only => [:show, :new, :create, :destroy, :edit] do
...
end
And I am added into a view a link for deleting a photo:
<%= button_to 'Delete', #photo, :method => :delete, :confirm => 'Are you sure?' %>
But this view returns the error:
undefined method `photo_path' for #<#<Class:0x007faef8172060>:0x007faef87a7908>
The destroy method is the method generated by scaffold. What do I have wrong?
EDIT: rake routes output:
root / photos#index
search GET /search(.:format) photos#search
voteup_user_photo GET /:user_id/:id/voteup(.:format) photos#voteup
votedown_user_photo GET /:user_id/:id/votedown(.:format) photos#votedown
user_photos POST /:user_id(.:format) photos#create
new_user_photo GET /:user_id/new(.:format) photos#new
edit_user_photo GET /:user_id/:id/edit(.:format) photos#edit
user_photo GET /:user_id/:id(.:format) photos#show
DELETE /:user_id/:id(.:format) photos#destroy
It appears that you have a nested route (path needs :user_id and :id). Try passing the path parameters explicitly:
button_to 'Delete', { :user_id => #user.id, :id => #photo.id }, :method => :delete, :confirm => 'Are you sure?'
If that doesn't work, you may need to include the :action in the options hash as well.

Ruby routes and custom action

I'm trying to incorporate Devise and Cancan into a web app. I want users with :role => "admin" to be able to delete users, and Devise's destroy action only allows users to delete themselves, so I've created a custom action for this purpose. (To override the plugin's controller file, I've copied the registrations controller over to app/controllers/registrations_controller.rb.)
Here is my custom action in my registrations_controller.rb:
def destroy_user_account
#user = User.find_by_id(params[:user])
#user.destroy
redirect_to profiles_path, :flash => { :success => "User deleted!" }
authorize! :destroy, User, :message => "You don't have authorisation to delete this user."
end
Here is how I'm trying to use it, in a link on the page where you view a user's profile. (I have things set up so that each user has_one profile; profiles are what you see at the front end. A profile is automatically created in the profiles table on user registration.)
<% if can? :update, #profile %>
| <%= link_to 'Edit Profile', edit_profile_path(#profile) %>
| <%= link_to 'Edit Settings', edit_settings_path %>
<% end %>
<% if can? :destroy, #profile.user %>
| <%= link_to "Delete User", destroy_user_account(#profile.user),
:class => "delete",
:confirm => "Are you sure?",
:title => "Delete #{#profile.user.name}"
%>
<% end %>
My tests are showing 2 failures that I can't resolve:
1) ProfilesController GET show when signed in as an admin should
have a link to edit the profile
Failure/Error: get :show, :id => #profile
ActionView::Template::Error:
undefined method destroy_user_account' for #<#<Class:0x105b474a8>:0x1057f32e8>
# ./app/views/profiles/show.html.erb:41:in_app_views_profiles_show_html_erb___917863454_2195331000_0'
# ./spec/controllers/profiles_controller_spec.rb:143
2) ProfilesController GET show when signed in as an admin should
have a link to delete the user's account (using the
destroy_user_account action in the registrations controller)
Failure/Error: get :show, :id => #profile
ActionView::Template::Error:
undefined method destroy_user_account' for #<#<Class:0x105b474a8>:0x105806d20>
# ./app/views/profiles/show.html.erb:41:in_app_views_profiles_show_html_erb___917863454_2195331000_0'
# ./spec/controllers/profiles_controller_spec.rb:148
Also, when I try it out in my browser, clicking on the "Delete user" link gets me the following error:
Routing Error
No route matches "/destroy-user-account/2"
Here are the routes that should cover this:
devise_for :users, #:path => '',
:skip => [ :confirmations, :passwords, :registrations ],
:controllers => { :registrations => "registrations" } do
# Routes for ACCOUNT REGISTRATIONS
get "join", :to => "registrations#new", :as => :new_user_registration
post "join", :to => "registrations#create", :as => :user_registration
get "settings/account", :to => "registrations#show", :as => :settings
get "settings/account/edit", :to => "registrations#edit", :as => :edit_settings
put "settings/account", :to => "registrations#update", :as => :update_settings
delete "close-my-account/:id", :to => "registrations#destroy", :as => :close_my_account
delete "destroy-user-account/:id", :to => "registrations#destroy_user_account", :as => :destroy_user_account
Can anyone help with what I'm doing wrong?
In the browser it isn't matching the route because you're sending a GET request but the route only matches a DELETE request. The test fails because the route gives the name destroy_user_account_path instead of destroy_user_account.
Try:
<%= link_to "Delete User", destroy_user_account_path(#profile.user),
:class => "delete",
:confirm => "Are you sure?",
:title => "Delete #{#profile.user.name}"
:method => :delete
%>

Named routes: why destroy_message_path doesn't work?

I am having a link like
<a href = '/messages/destroy/<%= #showmessage.id %>'>Delete Message</a>
I am rewriting this into
<%= link_to "Delete Message", destroy_message_path(:id => "1") %>
In my routes i have
map.resources :messages, :collection => { :destroy => :get }
And in my controller
def destroy
#message = Message.find(params[:id])
#message.destroy
redirect_to :action => 'index'
end
When I run the page, I am getting the error as:
undefined method `destroy_message_path' for #<ActionView::Base:0xb24a24c0>
How do I resolve this?
I'm not sure if you mean to be fighting against the Rails conventions here, but its alot easier to go along with them, so if you are ok with that you can do the following:
Remove this from your routes:
map.resources :messages, :collection => { :destroy => :get }
Change it to:
map.resources :messages
And use this link format instead:
<%= link_to "Delete Message", message_path(:id => "1"), :method => 'delete' %>
The URL for the destructive action will look like /messages/1, but the "method" portion of that link_to method will make Rails create a hidden form and perform a simulated "DELETE" action against the URL. Which is far more RESTful, and follows along with what Rails is expecting you to do.
With resources, you shouldn't be making a GET request, you should be making a DELETE request like this:
<%= link_to "Delete Message", destroy_message_path(:id => "1"),
:confirm => 'Are you sure?', :method => :delete %>
and in your routes file:
map.resources :messages
On another note, you can just pass in the object of the message to destroy_message_path, so for example:
<%= link_to "Delete Message", destroy_message_path(#message),
:confirm => 'Are you sure?', :method => :delete %>

Destroying users as an admin in Devise

I am trying to use Devise to delete users. I have a list of users each with their email and a 'delete' link next to them, only visible to me, the administrator. I want to be able to simply click the delete link to remove the user forever. The following code deletes me, the administrator!
<%= link_to "delete", user_registration_path, :method => :delete, :confirm => "You sure?" %>
I would think you need to pass the :id of the user you want to delete to some kind of 'destroy_user' method:
#user.find(params[:id]).destroy_user
But how do you do this when you have to submit a DELETE request to the user_registration_path??
------ EDIT --------
OK, I've added this method to my users controller:
def destroy
User.find(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to users_path
end
So, I need to tell the users controller to invoke the destroy method when it receives a DELETE request. How do you do this in routes.rb? Currently I have:
match '/users/:id', :to => 'users#show', :as => :user
match '/all_users', :to => 'users#index', :as => :all_users
I need something like:
match 'delete_user', :to => 'users#destroy', :as => :destroy_user, :method => :delete
but this doesn't work. And what should go in the link?:
<%= link_to "delete", destroy_user, :method => :delete, :confirm => "You sure?" %>
To put it another way, what should you put in the routes.rb file in order to distinguish between different request types (GET, DELETE etc) to the same url?
Replace 'user' by the actual user that you want to destroy, ex: if you're printing out the email as user.email, then plugin the user there et voilĂ 
<%= link_to "delete", user_registration_path(user), :method => :delete, :confirm => "You sure?" %>
Devise doesn't provide an action to delete another user, only to delete the currently logged in user. You'd have to create your own action in one of your controllers (most likely, whichever controller has the action to display all the users) to handle deleting a user other than the currently logged in one.
Got it! Simply needed to add the :via argument in routes:
match '/users/:id', :to => 'users#show', :as => :user, :via => :get
match '/users/:id', :to => 'users#destroy', :as => :destroy_user, :via => :delete

Resources