How do I remove the Devise route to sign up? - ruby-on-rails-3
I'm using Devise in a Rails 3 app, but in this case, a user must be created by an existing user, who determines what permissions he/she will have.
Because of this, I want:
To remove the route for users to sign up.
To still allow users to edit their profiles (change email address and password) after they have signed up
How can I do this?
Currently, I'm effectively removing this route by placing the following before devise_for :users:
match 'users/sign_up' => redirect('/404.html')
That works, but I imagine there's a better way, right?
Update
As Benoit Garret said, the best solution in my case is to skip creating the registrations routes en masse and just create the ones I actually want.
To do that, I first ran rake routes, then used the output to re-create the ones I wanted. The end result was this:
devise_for :users, :skip => [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end
Note that:
I still have :registerable in my User model
devise/registrations handles updating email and password
Updating other user attributes - permissions, etc - is handled by a different controller
Actual answer:
Remove the route for the default Devise paths; i.e.:
devise_for :users, path_names: {
sign_up: ''
}
you can do this in your model
# typical devise setup in User.rb
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
change it to:
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable
notice that the symbol :registerable was removed
That's it, nothing else is required. All routes and links to registration page are magically removed too.
I tried to do this as well, but a thread on the devise google group dissuaded me from searching for a really clean solution.
I'll quote José Valim (the Devise maintainer) :
There isn't a straight-forward option. You can either provide a patch
or use :skip => :registerable and add only the routes you want.
The original question was :
Is there any good way to remove a specific route (the delete route)
from Rails?
I had similar issue tried to remove devise_invitable paths for create and new :
before:
devise_for :users
rake routes
accept_user_invitation GET /users/invitation/accept(.:format) devise/invitations#edit
user_invitation POST /users/invitation(.:format) devise/invitations#create
new_user_invitation GET /users/invitation/new(.:format) devise/invitations#new
PUT /users/invitation(.:format) devise/invitations#update
after
devise_for :users , :skip => 'invitation'
devise_scope :user do
get "/users/invitation/accept", :to => "devise/invitations#edit", :as => 'accept_user_invitation'
put "/users/invitation", :to => "devise/invitations#update", :as => nil
end
rake routes
accept_user_invitation GET /users/invitation/accept(.:format) devise/invitations#edit
PUT /users/invitation(.:format) devise/invitations#update
note 1 devise scope https://github.com/plataformatec/devise#configuring-routes
note 2 I'm applying it on devise_invitable but it will work with any devise *able feature
Important note: see that devise_scope is on user not users ? that's correct, watch out for this ! It can cause lot of pain giving you this problem:
Started GET "/users/invitation/accept?invitation_token=xxxxxxx" for 127.0.0.1
Processing by Devise::InvitationsController#edit as HTML
Parameters: {"invitation_token"=>"6Fy5CgFHtjWfjsCyr3hG"}
[Devise] Could not find devise mapping for path "/users/invitation/accept? invitation_token=6Fy5CgFHtjWfjsCyr3hG".
This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example:
devise_scope :user do
match "/some/route" => "some_devise_controller"
end
2) You are testing a Devise controller bypassing the router.
If so, you can explicitly tell Devise which mapping to use:
#request.env["devise.mapping"] = Devise.mappings[:user]
I found another post similar to this one and wanted to share an answer #chrisnicola gave. In the post they were attempting to only block user signup's during production.
You could also modify the registrations controller. You can use something like this:
In "app/controllers/registrations_controller.rb"
class RegistrationsController < Devise::RegistrationsController
def new
flash[:info] = 'Registrations are not open.'
redirect_to root_path
end
def create
flash[:info] = 'Registrations are not open.'
redirect_to root_path
end
end
This will override devise's controller and use the above methods instead. They added flash messages incase that someone somehow made it to the sign_up page. You should also be able to change the redirect to any path you like.
Also in "config/routes.rb" you can add this:
devise_for :users, :controllers => { :registrations => "registrations" }
Leaving it like this will allow you to use the standard devise edit your profile. If you wish you can still override the edit profile option by including
def update
end
in the "app/controllers/registrations_controller.rb"
This is an old question - but I recently had solve the same issue and came up with a solution which is far more elegant than:
devise_for :users, :skip => [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end
And it gives the default names for the named routes (like cancel_user_registration) without being excessively verbose.
devise_for :users, skip: [:registrations]
# Recreates the Devise registrations routes
# They act on a singular user (the signed in user)
# Add the actions you want in 'only:'
resource :users,
only: [:edit, :update, :destroy],
controller: 'devise/registrations',
as: :user_registration do
get 'cancel'
end
rake routes output with the default devise modules:
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
user_registration PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
You can override the "devise_scope" by placing it before the "devise_for".
devise_scope :user do
get "/users/sign_up", :to => "sites#index"
end
devise_for :users
Not sure if this is the best way but its my solution currently, as it just redirects back to the sign in page.
I liked #max's answer, but when trying to use it I ran into an error due to devise_mapping being nil.
I modified his solution slightly to one that seems to address the issue. It required wrapping the call to resource inside devise_scope.
devise_for :users, skip: [:registrations]
devise_scope :user do
resource :users,
only: [:edit, :update, :destroy],
controller: 'devise/registrations',
as: :user_registration do
get 'cancel'
end
end
Note that devise_scope expects the singular :user whereas resource expects the plural :users.
Do This in routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}, :skip => [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end
devise_scope :user do
get "/sign_in", :to => "devise/sessions#new"
get "/sign_up", :to => "devise/registrations#new"
end
you will get an error now while you come to sign in page, to fix it.
Do this change in: app/views/devise/shared/_links.erb
<% if request.path != "/sign_in" %>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end -%>
<% end %>
I've found this to work well without messing with routes or adding application controller methods. My approach is to override the devise method. Add this to app/controllers/devise/registrations_controller.rb
I've omitted the other methods for brevity.
class Devise::RegistrationsController < DeviseController
...
# GET /resource/sign_up
def new
redirect_to root_path
end
....
end
Also to remove illusion that this path is still reachable from other views you might also want to remove this code from app/views/devise/shared/_links.erb
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end -%>
For others in my case.
With devise (3.5.2).
I successfully removed the routes to signup, but kept the ones to edit the profile, with the following code.
#routes.rb
devise_for :users, skip: [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put '/users(.:format)' => 'devise/registrations#update', as: 'user_registration'
patch '/users(.:format)' => 'devise/registrations#update'
end
Here's the slightly different route I went. It makes it so you don't have to override the devise/shared/_links.html.erb view.
In app/models/user.rb:
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable
In config/routes.rb:
devise_for :users
devise_scope :user do
put 'users' => 'devise/registrations#update', as: 'user_registration'
get 'users/edit' => 'devise/registrations#edit', as: 'edit_user_registration'
delete 'users' => 'devise/registrations#destroy', as: 'registration'
end
Before:
$ rake routes | grep devise
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
After:
$ rake routes | grep devise
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
user_registration PUT /users(.:format) devise/registrations#update
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
registration DELETE /users(.:format) devise/registrations#destroy
Instead of searching for a hard solution. I used the below approaches.
Delete the sign_up form from page (path devise/registrations/new.html.erb) and replace it with custom info.
Redirect the incoming traffic to some other page. Like below in routes.rb
get "/users/sign_up", to: redirect('/')
post "/users/sign_up", to: redirect('/')
Make sure to write it before devise_for :users
I had the same issue and I found it a bit bad practise to redirect users from the registration page. So my solution is basically is not using :registrable at all.
What I did was to create a similar page like edit user details which looked like:
<%= form_tag(update_user_update_path, method: :post) do %>
<br>
<%= label_tag(:currPassword, 'Current password:') %> <%= password_field_tag(:currPassword) %> <br>
<%= label_tag(:newPassword, 'New password:') %> <%= password_field_tag(:newPassword) %> <br>
<%= label_tag(:newPasswordConfirm, 'Confirm new password:') %> <%= password_field_tag(:newPasswordConfirm) %> <br>
<%= submit_tag('Update') %>
<% end %>
So this form submits into a new post end point that updates the password, which looks like:
def update
currPass = params['currPassword']
newPass1 = params['newPassword']
newPass2 = params['newPasswordConfirm']
currentUserParams = Hash.new()
currentUserParams[:current_password] = currPass
currentUserParams[:password] = newPass1
currentUserParams[:password_confirmation] = newPass2
#result = current_user.update_with_password(currentUserParams)
end
Later on you can use the #result in your view to tell the user whether the password is updated or not.
By changing the routes there are a whole bunch of other problems that come with that. The easiest method I have found is to do the following.
ApplicationController < ActionController::Base
before_action :dont_allow_user_self_registration
private
def dont_allow_user_self_registration
if ['devise/registrations','devise_invitable/registrations'].include?(params[:controller]) && ['new','create'].include?(params[:action])
redirect_to root_path
end
end
end
You could modify the devise gem itself. First, run this command to find the installed location of using:
gem which devise
Let's suppose the path is:
/usr/local/lib/ruby/gems/1.9.1/gems/devise-1.4.2/lib/devise
Then go to
/usr/local/lib/ruby/gems/1.9.1/gems/devise-1.4.2/lib/devise/lib/devise/rails and edit routes.rb in that directory. There is a method called def devise_registration(mapping, controllers) which you can modify to get rid of the new action. You can also completely remove the mappings for devise_registration
Related
no route matches controller (Rails 3)
I'm pretty new to RoR, please help me identify where I am wrong I get the following error Routing Error No route matches {:controller=>"groups"} Try running rake routes for more information on available routes when trying to render the following view <li><%= link_to 'My groups', user_groups_path %></li> <li><%= link_to 'New group', new_user_group_path %></li> and here is 'routes.rb' and rake routes output devise_for :users resources :users do |user| resources :groups do |group| resources :people do |person| end end end new_user_session GET /users/sign_in(.:format) devise/sessions#new user_session POST /users/sign_in(.:format) devise/sessions#create destroy_user_session GET /users/sign_out(.:format) devise/sessions#destroy user_password POST /users/password(.:format) devise/passwords#create new_user_password GET /users/password/new(.:format) devise/passwords#new edit_user_password GET /users/password/edit(.:format) devise/passwords#edit PUT /users/password(.:format) devise/passwords#update cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel user_registration POST /users(.:format) devise/registrations#create new_user_registration GET /users/sign_up(.:format) devise/registrations#new edit_user_registration GET /users/edit(.:format) devise/registrations#edit PUT /users(.:format) devise/registrations#update DELETE /users(.:format) devise/registrations#destroy user_group_people GET /users/:user_id/groups/:group_id/people(.:format) people#index POST /users/:user_id/groups/:group_id/people(.:format) people#create new_user_group_person GET /users/:user_id/groups/:group_id/people/new(.:format) people#new edit_user_group_person GET /users/:user_id/groups/:group_id/people/:id/edit(.:format) people#edit user_group_person GET /users/:user_id/groups/:group_id/people/:id(.:format) people#show PUT /users/:user_id/groups/:group_id/people/:id(.:format) people#update DELETE /users/:user_id/groups/:group_id/people/:id(.:format) people#destroy groups GET /users/:user_id/groups(.:format) groups#index POST /users/:user_id/groups(.:format) groups#create new_user_group GET /users/:user_id/groups/new(.:format) groups#new edit_user_group GET /users/:user_id/groups/:id/edit(.:format) groups#edit user_group GET /users/:user_id/groups/:id(.:format) groups#show PUT /users/:user_id/groups/:id(.:format) groups#update DELETE /users/:user_id/groups/:id(.:format) groups#destroy users GET /users(.:format) users#index POST /users(.:format) users#create new_user GET /users/new(.:format) users#new edit_user GET /users/:id/edit(.:format) users#edit user GET /users/:id(.:format) users#show PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroy here is 'model.rb' class User < ActiveRecord::Base has_many :groups class Group < ActiveRecord::Base belongs_to :user has_many :people please help me figure out how to fix the problem many thanks. UPD here is solution, it works I made all changes suggested by #Abibullah and two changes in controllers view: <li><%= link_to 'My groups', user_groups_path(current_user) %></li> <li><%= link_to 'New group', new_user_group_path(current_user) %></li> routes.rb resources :users do |user| resources :groups do |group| resources :people end end devise_for :users GroupsController.rb: def index #user = current_user #user.groups = Group.all was: def index #user = current_user #groups = Group.all end UsersController.rb class Devise::UsersController < DeviseController def show end end
To Create a nested Group Inside User, U need to pass the user_id inside which U are Creating the Group. For Ex: If I have user1 Then I will use the routes as this: link_to 'My groups', user_groups_path(user1) OR link_to 'My groups', user_groups_path(user1.id) AND link_to 'My Group', new_user_group_path(user1) OR link_to 'My Group', new_user_group_path(user1.id) This is to tell that, To which User you are creating the Group. If U want to access any specific Group, say for ex: grp1 then My url will be link_to 'My Group', user_group_path(user1, grp1) THis is a good refrence for routing. http://guides.rubyonrails.org/routing.html
I think it's obvious. You've got a typo in your <li><%= link_to 'My groups', user_groups_path %></li> link. The path should be user_group_path (without the 's') as shown in your rake routes output, instead of the one you've written in your link.
Devise, can't log out
In a Rails app, I use devise to manage my users and my link to destroy a session no longer work. It was working, and now I have add active admin, It doesn't. My link is <%= link_to "Déconnexion", destroy_user_session_path, :method => :delete, :class => 'button' %> My routes.rb devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks"} My rake routes destroy_user_session DELETE /users/sign_out(.:format) And it try to open the view /users/sign_out, so I have : ActiveRecord::RecordNotFound in UsersController#show Couldn't find User with id=sign_out Does Active_admin and Devise crash together? It will be weird 'cause active use devise, no? Edit: For the next person who will have this issue, I solved it by adding the next line to /config/initializers/devise.rb. config.sign_out_via = :get Not exactly the finest way, but it does the job.
Posting Jeff Paquette's comment as an answer. Update the config/initializers/active_admin.rb with: config.logout_link_method = :delete
Please make changes in your routes.rb :- devise_scope :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks"} do get "/users/sign_out", :to => "devise/sessions#destroy" end I am also getting same problem, only this can resolve me after 1hr time wasting. Thanks.
rails3: action being routed to the wrong controller. Possible bug?
I have two models (user & profile) with a 1-to-1 association. class Profile < ActiveRecord::Base attr_accessible :language_tokens, :tele, :languages, :serviceDesc, :service belongs_to :user ... class User < ActiveRecord::Base has_one :profile, dependent: :destroy The profile is built using: #profile = #user.build_profile(session[:form_params]) my profile edit form is just a standard form which should be routed to my profile update action upon submission. <%= form_for #profile do |f| %> <%= render 'shared/host_information', :f => f%> <%= render 'shared/service_information', :f => f%> <%= f.submit 'done', class: "bnt"%> <% end %> HTML form: <form id="edit_profile_6" class="edit_profile" method="post" action="/profiles/6" accept-charset="UTF-8"> However, for some bizarre reason, the form is being submitted to user update instead of the expected profile update. I put a debug point in user update and you can see that the params confirm that the target controller should indeed be profiles_controller. /railsapp/loco_app/app/controllers/users_controller.rb:82 #user = User.find_by_id(params[:id]) (rdb:15) p params {"utf8"=>"✓", "_method"=>"put", "authenticity_token"=>"qXx5EWwIWASiARKVFE7eDd43gHnBSmK538YAXeesDyI=", "profile"=>{"country_id"=>"8", "city_id"=>"22", "tele"=>"", "language_tokens"=>"18,14", "service"=>"9", }, "commit"=>"done", "action"=>"update", "controller"=>"profiles", "id"=>"6"} (rdb:15) here are the relevant routes: profiles POST /profiles(.:format) profiles#create new_profile GET /profiles/new(.:format) profiles#new edit_profile GET /profiles/:id/edit(.:format) profiles#edit profile PUT /profiles/:id(.:format) profiles#update users GET /users(.:format) users#index POST /users(.:format) users#create new_user GET /users/new(.:format) users#new edit_user GET /users/:id/edit(.:format) users#edit user GET /users/:id(.:format) users#show PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroy What's the best way to debug this problem? Is this some weird side-effect of a 1-to-1 association or is there a bug here? I'm using rails 3.2.2. *UPDATE* So this definitely looks like a bug. I regenerated my controller (same name) and copied over the same code and now it's working without any other changes. I'm still interested in knowing whether this is a known issue and how to debug problems like this in the future.
How to reroute standard rest actions to devise controller?
I have been building devise into a small Rails app. It's a pretty standard setup but one wrinkle is that the default authentication rules need to be changed for this project. Non-idempotent registration actions must all be restricted to only authenticated users. To do this, I've written a custom registrations controller and linked it up in the routing. All the custom controller really has to do is alter the filtering requirements. Based on the Rails controller filtering documentation, I got this working with a minimum of effort. But by itself that only applies to devise-specific actions like /users/sign_up or /users/edit. I would also like to wire in the standard Rails actions (/users/new, /users/1/edit, etc) to the custom controller. I can get the action to instantiate the controller -- leading the horse to water so to speak -- but when the action is new instead of sign_up, it crashes out during the filtering. The problem appears to be that resource_name yields nil when the action is 'new', but is fine when it's 'sign_up'. I don't understand why devise cares or where the distinction is represented in code. I've looked at other questions like Update the User controller of devise and Override devise registrations controller and Custom Devise controller but they don't get into this issue. The specific error I am getting is NoMethodError in RegistrationsController#new undefined method `name' for nil:NilClass and the top of the trace is devise (2.1.2) app/controllers/devise_controller.rb:22:in resource_name' app/controllers/registrations_controller.rb:104:in authenticate_scope!' It is apparently happening the first time devise_mapping is referenced. But as per the above stackoverflow question I have also explicitly provided helpers for devise_mapping, and they don't even get called. Can anyone explain or help me figure out where to look further? from routes.rb: Fs::Application.routes.draw do devise_for :users, :controllers => { :registrations => 'registrations' } resources :users, :except => [:index, :show], :controller => 'registrations' resources :users, :only => [:index, :show] [...] rake routes reports: new_user_session GET /users/sign_in(.:format) devise/sessions#new user_session POST /users/sign_in(.:format) devise/sessions#create destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy user_password POST /users/password(.:format) devise/passwords#create new_user_password GET /users/password/new(.:format) devise/passwords#new edit_user_password GET /users/password/edit(.:format) devise/passwords#edit PUT /users/password(.:format) devise/passwords#update cancel_user_registration GET /users/cancel(.:format) registrations#cancel user_registration POST /users(.:format) registrations#create new_user_registration GET /users/sign_up(.:format) registrations#new edit_user_registration GET /users/edit(.:format) registrations#edit PUT /users(.:format) registrations#update DELETE /users(.:format) registrations#destroy users POST /users(.:format) registrations#create new_user GET /users/new(.:format) registrations#new edit_user GET /users/:id/edit(.:format) registrations#edit user PUT /users/:id(.:format) registrations#update DELETE /users/:id(.:format) registrations#destroy GET /users(.:format) users#index GET /users/:id(.:format) users#show my registrations_controller.rb: class RegistrationsController < Devise::RegistrationsController prepend_before_filter :authenticate_scope!, :except => [:index, :show] skip_filter :require_no_authentication end my users_helper.rb: module UsersHelper # used by devise def resource_name :user end def resource #resource ||= User.new end def devise_mapping #devise_mapping ||= Devise.mappings[:user] end end using: Rails 3.2.6 Ruby 1.9.3 devise 2.1.2 Update: pasted in the correct trace output.
So one solution appears to be to add devise_scope :user do get '/users/new' => 'registrations#new' end into routes.rb. This may not be the best answer but it works.
No route matches [GET] "/users/sign_out"
Here is my actual error: No route matches [GET] "/members/sign_out" Since most people will use "users" I thought it would be more helpful to have that in the title. At any rate, I am essential unable to logout. I can successfully edit my member profile. I am using devise 1.4.2 and Rails 3.1.0.rc4. Also, I have generated two separate devise models - one called "members" and the other called "admins". I was able to register and log into both of them (simultaneously) by manually navigating to the correct URL path (i.e., localhost:3000/admins/sign_in/). I created some links within my application.html.haml layout file by following this RailsCast on Devise. I am aware that it only addresses signin/signout links for "members." If I click on the signout link I get the above error. This occurs if I manually navigate to either signout URL (i.e., localhost:3000/admins/sign_out/). Can someone tell me why this is happening? Below are the various related files. And of course, I'm a newbie... rake routes output: j(film_repo)$ rake routes new_member_session GET /members/sign_in(.:format) {:action=>"new", :controller=>"devise/sessions"} member_session POST /members/sign_in(.:format) {:action=>"create", :controller=>"devise/sessions"} destroy_member_session DELETE /members/sign_out(.:format) {:action=>"destroy", :controller=>"devise/sessions"} member_password POST /members/password(.:format) {:action=>"create", :controller=>"devise/passwords"} new_member_password GET /members/password/new(.:format) {:action=>"new", :controller=>"devise/passwords"} edit_member_password GET /members/password/edit(.:format) {:action=>"edit", :controller=>"devise/passwords"} PUT /members/password(.:format) {:action=>"update", :controller=>"devise/passwords"} cancel_member_registration GET /members/cancel(.:format) {:action=>"cancel", :controller=>"devise/registrations"} member_registration POST /members(.:format) {:action=>"create", :controller=>"devise/registrations"} new_member_registration GET /members/sign_up(.:format) {:action=>"new", :controller=>"devise/registrations"} edit_member_registration GET /members/edit(.:format) {:action=>"edit", :controller=>"devise/registrations"} PUT /members(.:format) {:action=>"update", :controller=>"devise/registrations"} DELETE /members(.:format) {:action=>"destroy", :controller=>"devise/registrations"} new_admin_session GET /admins/sign_in(.:format) {:action=>"new", :controller=>"devise/sessions"} admin_session POST /admins/sign_in(.:format) {:action=>"create", :controller=>"devise/sessions"} destroy_admin_session DELETE /admins/sign_out(.:format) {:action=>"destroy", :controller=>"devise/sessions"} admin_password POST /admins/password(.:format) {:action=>"create", :controller=>"devise/passwords"} new_admin_password GET /admins/password/new(.:format) {:action=>"new", :controller=>"devise/passwords"} edit_admin_password GET /admins/password/edit(.:format) {:action=>"edit", :controller=>"devise/passwords"} PUT /admins/password(.:format) {:action=>"update", :controller=>"devise/passwords"} cancel_admin_registration GET /admins/cancel(.:format) {:action=>"cancel", :controller=>"devise/registrations"} admin_registration POST /admins(.:format) {:action=>"create", :controller=>"devise/registrations"} new_admin_registration GET /admins/sign_up(.:format) {:action=>"new", :controller=>"devise/registrations"} edit_admin_registration GET /admins/edit(.:format) {:action=>"edit", :controller=>"devise/registrations"} PUT /admins(.:format) {:action=>"update", :controller=>"devise/registrations"} DELETE /admins(.:format) {:action=>"destroy", :controller=>"devise/registrations"} films GET /films(.:format) {:action=>"index", :controller=>"films"} POST /films(.:format) {:action=>"create", :controller=>"films"} new_film GET /films/new(.:format) {:action=>"new", :controller=>"films"} edit_film GET /films/:id/edit(.:format) {:action=>"edit", :controller=>"films"} film GET /films/:id(.:format) {:action=>"show", :controller=>"films"} PUT /films/:id(.:format) {:action=>"update", :controller=>"films"} DELETE /films/:id(.:format) {:action=>"destroy", :controller=>"films"} root / {:controller=>"films", :action=>"index"} routes.rb FilmRepo::Application.routes.draw do devise_for :members devise_for :admins resources :films root :to => 'films#index' end admin.rb (model) class Admin < ActiveRecord::Base # Include default devise modules. Others available are: # :token_authenticatable, :encryptable, :confirmable, :lockable, and :omniauthable devise :database_authenticatable, :registerable, :timeoutable, :recoverable, :rememberable, :trackable, :validatable # Setup accessible (or protected) attributes for your model attr_accessible :email, :password, :password_confirmation, :remember_me end member.rb (model) class Member < ActiveRecord::Base # Include default devise modules. Others available are: # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable # Setup accessible (or protected) attributes for your model attr_accessible :email, :password, :password_confirmation, :remember_me end application.html.haml !!! %html %head %title Film Repo = stylesheet_link_tag 'compiled/screen.css', :media => 'screen, projection' = stylesheet_link_tag 'compiled/print.css', :media => 'print' /[if lt IE 8] = stylesheet_link_tag 'compiled/ie.css', :media => 'screen, projection' = csrf_meta_tag %body.bp #container #user_nav - if member_signed_in? Signed in as #{current_member.email}. Not you? \#{link_to "Sign out", destroy_member_session_path} - else = link_to "Sign up", new_member_registration_path or #{link_to "sign in", new_member_session_path} - flash.each do |name, msg| = content_tag :div, msg, :id => "flash_#{name}" = yield
You can end a session via get by changing the devise configuration in initializers. # The default HTTP method used to sign out a resource. Default is :delete. config.sign_out_via = :get Just open the link and your session is removed.
I had a similar problem, but addition of the :method=> :delete didn't work. I was able to add a new route for a the get request by commenting out the devise_for :users and adding devise_for :users do get '/users/sign_out' => 'devise/sessions#destroy' end
I had a similar problem. My view code was like this: <%= link_to " exit", destroy_user_session_path, method: :delete %> After adding the following change to routes.rb it worked, devise_for :users devise_scope :user do get '/users/sign_out' => 'devise/sessions#destroy' end
Although I don't know the cause, the reason why you are getting that message is because in your routes you have destroy_member_session DELETE /members/sign_out(.:format) {:action=>"destroy", :controller=>"devise/sessions"} Which means that route is only available with the DELETE method as opposed to GET. This is a bit weird since in the docs for devise it says that it should create it as GET route (https://github.com/plataformatec/devise/blob/master/lib/devise/rails/routes.rb#L30) With it as a DELETE route, you should be able to logout using link_to :logout, destroy_member_session_path, :method => :delete
I just needed to add the //= require jquery //= require jquery_ujs to my application.js
If you want to use :delete method for security reasons and not be dependent on jquery-ujs you can use button_to instead of link_to, like: button_to "Log out", destroy_user_session_path, method: :delete if using link_to you must be sure to have javascript active: Note that if the user has JavaScript disabled, the request will fall back to using GET. As seen in docs
In devise.rb, change config.sign_out_via = :delete to config.sign_out_via = :get This worked for me. I went crazy with this because the default is delete and I don’t understand why. This works, but I am not sure whether it affects other elements in the application.
We still can use :method => :delete in my code, like that = link_to "Sign out", destroy_user_session_path,:method => :delete The reason i think we fail to load javascript that include jquery, make sure = javascript_include_tag "application" (haml- you can use html too) to include jquery-ui and jquery-ujs. So if it still error, i suggest to change rails gem in GEMFILE to version 3.2.6 and call bundle update to update gems. It works for me!
= link_to "Sign out", destroy_user_session_path,:method => :delete will NOT work instead use this, = link_to "Sign out", destroy_user_session_path,:method => 'delete' should do the trick or worse case add require jquery_ujs in your application.js
In Rails 6: I just changed the link_to to button_to, and the 'sign out' works properly <%= button_to "Sign out", destroy_user_session_path, method: :delete %>
In rails 7, you need to add data: { turbo_method: :delete" } to link_to. So the link_to would look like this <%= link_to "Log out", destroy_user_session_path, data: { turbo_method: :delete } %>
Using Rails4, I had to use the following method: <%= link_to "Logout", destroy_admin_session_path, method: :delete %> Emphasis on where the colons are on method: and :delete
Maybe that will help somebody. Upgraded from Rails 3.0 to 3.1 and found this problem. This fixed it for me: routes.rb: devise_for: users devise.rb: config.sign_out_via = :delete application.html.erb: <%= javascript_include_tag "application" %> * not :defaults _login_items.html.erb: <%= link_to('Logout', destroy_user_session_path, :method => :delete) %> app/assets/javascripts/application.js //= require jquery //= require jquery-ui //= require jquery_ujs //= require_tree . and I had in javascript/ jquery.js, jquery_ujs.js from 3.0 version that I've removed.
You may have removed assets/javascripts/* Run rails generate jquery:install --ui this will generate all the javascripts as shown below xxxx#xxxxx:~/Projects/Rails_apps/rtest$ rails generate jquery:install --ui remove public/javascripts/prototype.js remove public/javascripts/effects.js remove public/javascripts/dragdrop.js remove public/javascripts/controls.js copying jQuery (1.7.1) create public/javascripts/jquery.js create public/javascripts/jquery.min.js copying jQuery UI (1.8.16) create public/javascripts/jquery-ui.js create public/javascripts/jquery-ui.min.js copying jQuery UJS adapter (822920) remove public/javascripts/rails.js create public/javascripts/jquery_ujs.js Go to your layout e.g application.html.erb and edit <%= javascript_include_tag :all %> That worked for me :)
FWIW I have also run into this problem. Have looked into all of the suggested answers however the only one which worked was to foto open routes.rb and comment out the following line: devise_for :users Below that, add the following line: devise_for :users do get '/users/sign_out' => 'devise/sessions#destroy' end
The problem begins with rails 3.1 in assets/javascript/. Just look for application.js, and if the file doesn't exist, create a file with that name. I don't know why my file disappears or never was created on rails new app... that file is the instance for jquery.
#creamhost say, devise_for :users do get '/users/sign_out' => 'devise/sessions#destroy' end but it is not correct solution for me (Rails4). I solved our problem (#Olives' answer), link_to :logout, destroy_member_session_path, method: :delete
I am using rails version 5. I encounter this problem also. The simple fix I did was to changing the devise configuration in initializes to the default. From : config.sign_out_via = :get To : config.sign_out_via = :delete
Keep your devise.rb using the correct HTTP method: # good config.sign_out_via = :delete # bad config.sign_out_via = :get Use button_to instead of link_to # good = button_to "Sign Out", destroy_user_session_path, method: :delete # bad = link_to "Sign Out", destroy_user_session_path, method: :delete" If you are using bootstrap (keep it classy) = link_to "Sign Out", destroy_user_session_path, method: :delete, class: "btn btn-default btn-sm" Ref: github.com/heartcombo/devise/issues/4570#issuecomment-740812109
Just use the following for your sign out link: <%= link_to "Sign out", destroy_user_session_path, method: :delete %>
//= require jquery_ujs You are missing this line in your assets. There's no need to get /users/signout request. Put this line into JavaScript file at very top of the page.
Had the same problem and remembered it only started happening after I decided to "clean up" my Javascript files. So I ran rails generate jquery:install --ui again and this solved it for me. (You can ignore the --ui part if you don't need JQuery UI, I suppose.)
devise_for :users devise_scope :user do get '/users/sign_out' => 'devise/sessions#destroy' end That works for me
I believe this error is due to devise library template not aligned with changes on rails 7, In short, you are not sending the request in method delete as expected due to the Javascript library that does that is now missing. you can change : <%= link_to "Sign out", destroy_user_session_path, :method => :delete %> with <%= link_to "Sign out", destroy_user_session_path, data: { "turbo-method": :delete }, class: "btn btn-danger ml-3" %> And it will work again
This worked for me: <%= link_to 'Sign out', destroy_user_session_path, data: { turbo_method: :delete } %>
It happens only on windows.. Add the following thing to your Application.html.erb file. devise_for :users devise_scope :user do get '/users/sign_out' => 'devise/sessions#destroy' end