Aucun itinéraire ne correspond aux rails de devise «/ users / sign_out» 3

386

J'ai installé devise sur mon application et appliqué les éléments suivants dans mon application.html.erbfichier:

<div id="user_nav">
    <% if user_signed_in? %>
        Signed in as <%= current_user.email %>. This cannot be cheese?
        <%= link_to 'Sign out', destroy_user_session_path %>
    <% else %>
        <%= link_to 'Register', new_user_registration_path %> or <%= link_to 'Sign in', new_user_session_path %>
    <% end %>
</div>

J'ai couru rake routeset confirmé que tous les itinéraires sont valides.

Aussi, dans mon routes.rbdossier, j'ai devise_for :userset root :to => "home#index".

J'obtiens l'erreur de routage suivante en cliquant sur le lien "Déconnexion":

No route matches "/users/sign_out"

Des idées qui sont à l'origine de l'erreur?

vich
la source
1
Avez-vous redémarré votre application après avoir ajouté les itinéraires? Les changements de route ne deviennent effectifs qu'au démarrage.
Thilo-Alexander Ginkel
2
Oui. Je l'ai juste refait pour être en sécurité. De plus, j'ai lu ailleurs sur Stack qu'il pourrait y avoir un problème avec le nouveau bijou de devise non compatible avec Rails 3.0.3, j'ai donc essayé de changer ma gemme de devise de 1.4.2 à gem 'devise', :git => 'git://github.com/plataformatec/devise.git'. Mais cela n'a rien fait.
vich
Changer l'entrée dans le Gemfile ne vous procurerait-il pas simplement une version toujours plus récente de Devise? Avez-vous essayé de spécifier un numéro de version inférieur?
Leo Cassarani
Pourriez-vous publier votre fichier routes.rb
felix
1
La deuxième réponse de Jessie ci-dessous a parfaitement fonctionné.
vich

Réponses:

568

Je pense que l'itinéraire pour se déconnecter est une DELETEméthode. Cela signifie que votre lien de déconnexion doit ressembler à ceci:

<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>

Le vôtre n'inclut pas la :method => :deletepartie. Veuillez également noter que pour que cela fonctionne, vous devez également inclure <%= javascript_include_tag :defaults %>votre fichier de mise en page ( application.html.erb).

Jessie Dedecker
la source
3
Je peux dire en toute sécurité que je n'ai jamais eu à le faire dans aucune de mes applications Rails. link_to "Sign out", destroy_user_session_patha toujours été assez bon pour moi.
Leo Cassarani
8
J'ai fait le test et ça marche pour moi. N'oubliez pas que les choses changent d'une version à l'autre (que ce soit dans Rails ou Devise). De plus, la déconnexion est un comportement qui change d'état et qui ne devrait pas être fait en utilisant les méthodes GET (à mon humble avis).
Jessie Dedecker
23
Pour plus d'informations, la raison pour laquelle cela a été modifié dans la dernière version de Devise est décrite ici et ici .
Jessie Dedecker
6
J'ai rencontré ce même problème et la suggestion de Jessie a fonctionné pour moi. Je m'attends à ce que tous ceux qui traversent la rampe de rails finissent par se retrouver ici à cause de ce changement ...
johnnygoodman
2
vous pouvez également taper ceci dans votre console Web pour le tester $("<a href='/users/sign_out' data-method='delete'>Sign out</a>").appendTo('body');- si jQuery est chargé sur la page.
mraaroncruz
133

J'ai changé cette ligne dans devise.rb:

config.sign_out_via = :delete

à

config.sign_out_via = :get

et ça a commencé à marcher pour moi.

kitdesai
la source
22
La façon dont cela était fait auparavant était de se déconnecter en utilisant "GET / users / sign_out", mais ils l'ont changé en "DELETE" pour le rendre plus RESTful. L'auteur a expliqué qu'un GET ne devrait pas apporter de modifications au serveur telles que la déconnexion.
Jonathan Allard
2
cela a fonctionné pour moi. Bien que j'apprécie que ce n'est pas une meilleure pratique, les autres réponses ont échoué. Je ne vois pas pourquoi !!
Mild Fuzz
8
Il est également possible d'utiliser un tableau si vous souhaitez prendre en charge plusieurs méthodes. Par exemple: config.sign_out_via = [ :post, :delete ]ou devise_for :users, :sign_out_via => [ :post, :delete ], comme décrit dans devise / rails / routes.rb .
Hosam Aly
2
Je n'utiliserais pas une demande GET pour se déconnecter car cela ouvre l'utilisateur à une attaque XSRF. (Hacker crée un site Web avec une balise d'image avec src = " foo.com/users/sign_out ", l'utilisateur le visite et est déconnecté).
Ryan Doherty
1
@RyanDoherty Id Je ne me trompe pas, XSRF est toujours possible (l'attaquant n'a qu'à utiliser un formulaire avec action = "DELETE" sur l'url cible, puis le soumettre automatiquement au chargement de la page).
Maël Nison
60

Vous n'avez probablement pas inclus de fichier javery_ujs javascript. Assurez-vous que vous utilisez la dernière version de jquery-ujs: https://github.com/rails/jquery-ujs et les derniers fichiers disponibles:

rails generate jquery:install

Vous ne devriez plus avoir de fichier rails.js. Si vous le faites, vous êtes probablement obsolète. Assurez-vous également que ce fichier est chargé avec des valeurs par défaut, dans config / application.rb

config.action_view.javascript_expansions[:defaults] = %w(jquery.min jquery_ujs)

(Encore une fois, vous ne devriez pas avoir de fichier rails.js ici). Enfin, ajoutez le lien tel que documenté sur Devise wiki (style haml):

= link_to('Logout', destroy_user_session_path, :method => 'delete')

Et tout ira bien.

Gravis
la source
8
J'avais: method => 'delete' dans mon link_to, le problème n'était pas jquery_ujs inclus, cette solution a résolu mon problème. N'oubliez pas de mettre des «jquery-rails» de gemmes dans votre gemfile.
Rob Bazinet du
2
Merci, cela a fonctionné pour moi. Au lieu d'utiliser les valeurs par défaut, vous pouvez également utiliserjavascript_include_tag "jquery_ujs"
Bnicholas
Bonne prise, merci! J'utilise require.js pour charger des fichiers de manière asynchrone et j'ai oublié d'exiger jquery_ujs.
Dan Fairaizl
J'ai supposé que le «u» signifiait non compressé et j'ai supprimé cette ligne de application.js. Mauvaise supposition, je suppose. Merci.
Jeff
Ce problème est apparu (dans mon application basée sur le 100e appareil) après avoir changé le bootstrap twitter de less en sass et j'ai oublié de rajouter le // = require jquery_ujs dans mon application.js.
Joe
31

La possibilité de faire du lien de déconnexion un appel DELETE RESTful nécessite un attribut html data-method = "delete"en utilisant le code rails = link_to('Logout', destroy_user_session_path, :method => :delete).

Cependant, si vous n'avez pas jquery-ujsinstallé la gemme ou n'appelez pas le javascript résultant dans votre application.html via = javascript_include_tag "application", la réponse sera envoyée sous forme de demande GET et l'itinéraire échouera.

Vous avez quelques options si vous ne souhaitez pas utiliser jquery-ujsou ne pouvez pas trouver un moyen de le faire fonctionner:

  1. Changez config.sign_out_viaen égal à l' :getintérieur devise.rb(non recommandé, car SUPPRIMER est la requête RESTful appropriée)
  2. OU Changez link_topour = button_to('Logout', destroy_user_session_path, :method => :delete). Avec button_toRails fera le gros du travail en effectuant l'appel DELETE approprié. Vous pouvez ensuite styliser le bouton pour qu'il ressemble à un lien si vous le souhaitez.
Will Nathan
la source
Le passage de link_to à button_to a fonctionné pour moi, mais je ne comprends vraiment pas pourquoi? Qu'est-ce qui a changé en dehors du html / css?
Spyros Mandekis
1
Cela a à voir avec la magie des rails qui génère automatiquement du code HTML à partir de fonctions comme button_to et link_to. Il se trouve que la magie des rails pour button_to spécifie l'appel RESTful DELETE approprié et link_to ne le fait pas. Si je devais deviner, je dirais que la raison est que les éléments de bouton html peuvent gérer un appel DELETE (ou un bundle avec un champ caché spécifiant l'action) alors que les liens réguliers ne le peuvent pas.
Will Nathan
Merci pour cela. J'ai configuré mon application pour gérer manuellement jquery, donc je n'avais pas jquery-ujs. L'installation avec bower ou bundler et l'inclusion de la ligne appropriée pour le pipeline d'actifs résout le problème.
jrhorn424
1
Cela me semble la solution la plus sûre et la plus portable.
À propos button_to, Rails génère un formpour toute l'action. C'est pourquoi il est possible d'utiliser la :deleteméthode avec button_toet non avec link_to, il suffit de voir le code HTML généré.
Fernando Fabreti
25

Essayez d'ajouter une nouvelle route pour concevoir / sessions # destroy et de créer un lien vers cela. Par exemple:

routes.rb
devise_for :users do
  get 'logout' => 'devise/sessions#destroy'
end

vue:

<%= link_to "Logout", logout_path %>
Kevin Tsoi
la source
Obtention de la même erreur que mmichael. Ce test ci-dessus fonctionne pour moi.
rtfminc
1
J'ai également eu la même erreur que mmichael. La solution ci-dessus fonctionnera mais ce n'est pas comme cela qu'elle devrait être corrigée. Les itinéraires par défaut dans Devise incluent déjà l'itinéraire de déconnexion en tant que méthode DELETE. Vous ne devriez normalement pas avoir besoin de modifier les itinéraires par défaut eux-mêmes. C'est pourquoi vous pouvez le corriger en ajoutant simplement un paramètre distinct à l' link_toappel, comme décrit dans l'autre réponse.
Jessie Dedecker
Vous n'avez pas besoin d'ajouter une route au fichier route.rb, devise vous permet de changer la méthode dans devise.rb qui se trouve dans le répertoire / confit / initializers /.
Travis Pessetto
6
Ne jamais avoir de chemin de déconnexion en tant que GET.
Jagira
@Jagira pourquoi? Pourquoi pas DELETE et GET?
hrdwdmrbl
14

Utilisez-le dans votre fichier routes.rb:

devise_for :users do
    get '/users/sign_out' => 'devise/sessions#destroy'
end
Uma Maheswararao
la source
13

J'ai eu le même problème avec les rails 3.1.0, et j'ai résolu d'ajouter au fichier les lignes suivantes:

app/assets/javascripts/application.js
//= require_tree
//= require jquery
//= require jquery_ujs
gringo
la source
Si vous utilisez bower, essayez // = nécessite jquery-ujs.
monteirobrena
10

À une exception près, la réponse de Jessie a fonctionné pour moi:

<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>

changement:

:delete

... à:

'delete'

Donc, le code qui a fonctionné pour moi est:

<%= link_to "Sign out", destroy_user_session_path, :method => 'delete' %>
Galen
la source
Merci d'avoir publié cet extrait de code, sign_out fonctionne pour moi maintenant.
buk
9

Beaucoup de réponses à la question déjà. Pour moi, le problème était double:

  1. lorsque j'élargis mes itinéraires:

    devise_for :users do 
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  2. Je recevais un avertissement indiquant que ce montant est amorti, je l'ai donc remplacé par:

    devise_scope :users do
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  3. Je pensais que je supprimerais ma jQuery. Mauvais choix. Devise utilise jQuery pour "falsifier" la demande DELETE et l'envoyer en tant que GET. Vous devez donc:

    //= require jquery
    //= require jquery_ujs
  4. et bien sûr le même lien que beaucoup mentionné précédemment:

    <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
Lukasz Muzyka
la source
pouvez-vous expliquer le 3ème point ... j'en ai été victime et je veux le comprendre davantage
Rahul Dess
1
Certainement. Votre site Web n'envoie pas vraiment de demandes DELETE. Franchement, il n'utilisera que GET et POST. Parce que dans la communauté Rails, il a été convenu que (pour de bonnes raisons) nous voulons supprimer les enregistrements lors de la soumission de la demande DELETE, nous devons utiliser une petite astuce. Lorsque vous êtes dans votre ERB, vous spécifiez la méthode:: delete rails convertira cela en balise HTML5: data-method = "delete" et le soumettra comme GET. Maintenant, c'est là que jQuery-ujs et jQuery entrent en jeu. Ils permettent à l'application de reconnaître que c'est ce que vous faites. Pour que votre demande puisse être associée à l'action du contrôleur.
Lukasz Muzyka
sans ces joyaux, cela ne fonctionnera pas. Bien sûr, vous pouvez modifier les paramètres de devise (dans l'initialiseur de devise) et lui demander d'utiliser GET au lieu de DELETE.
Lukasz Muzyka,
7

Ajouter:

  <%= csrf_meta_tag %>  and 
  <%= javascript_include_tag :defaults %>  to layouts

Utilisez ces balises link_to

 link_to 'Sign out', destroy_user_session_path, :method => :delete

  or

 link_to 'Sign out', '/users/sign_out', :method => :delete

Dans les itinéraires, ajoutez:

  devise_for :users do
    get '/users/sign_out' => 'devise/sessions#destroy'
  end
Amal Kumar S
la source
7

Une autre option consiste à configurer la déconnexion pour être un GET au lieu d'un DELETE, vous pouvez le faire en ajoutant la ligne suivante sur /config/initializers/devise.rb

config.sign_out_via = :get

Mais comme Steve Klabnik l'a écrit sur son blog (http://blog.steveklabnik.com/2011/12/11/devise-actioncontroller-routingerror-no-route-matches-get-slash-users-slash-sign-out.html ) essayez d'utiliser DELETE en raison de la sémantique de cette méthode.

Rodrigo Flores
la source
Seule cette réponse a fonctionné pour moi pour Devise 3.5.1 & Rails 4.2.3
sagar junnarkar
N'oubliez pas de redémarrer le serveur :)
jackmin
6

Si vous utilisez Rails 3.1, assurez-vous que votre déconnexion application.html.erb ressemble à:

<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>

Et que votre ligne d'inclusion javascript ressemble à ce qui suit

<%= javascript_include_tag 'application' %>

Je suppose que certaines gemmes écrasent la nouvelle structure de l'emplacement default.js.

StlTenny
la source
Merci! Cela me rendait fou!
Dorian
5

Vérifiez-le avec le code source dans github:

https://github.com/plataformatec/devise/commit/adb127bb3e3b334cba903db2c21710e8c41c2b40#lib/generators/templates/devise.rb (date: 27 juin 2011)

  • # La méthode HTTP par défaut utilisée pour déconnecter une ressource. La valeur par défaut est: get. 188
  • # config.sign_out_via =: obtenez 187
  • # La méthode HTTP par défaut utilisée pour déconnecter une ressource. La valeur par défaut est: supprimer. 188
  • config.sign_out_via =: supprimer
Shane
la source
5

Eh bien, les gars pour moi, c'était seulement supprimer la: méthode =>: supprimer

<%= link_to('Sign out', destroy_user_session_path) %>
rêveur
la source
5

Cela signifie que vous n'avez pas généré les fichiers jquery après avoir installé la gemme jquery-rails. Vous devez donc d'abord le générer.

rails generate devise:install

Première option:

Cela signifie que vous devez modifier la ligne suivante sur /config/initializers/devise.rb

config.sign_out_via =: supprimer vers config.sign_out_via =: obtenir

Deuxième option:

Vous modifiez cette ligne <%= link_to "Sign out", destroy_user_session_path %>pour <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>le fichier de vue.

N'est généralement :method => :deletepas écrit par défaut.

Deepak Lamichhane
la source
5

Je veux ajouter à cela même si c'est un peu vieux.

le lien "sign_out" n'a pas fonctionné, malgré le fait que: method =>: delete.

Le commentaire indiquant que cela <%= javascript_include_tag :defaults %>doit être inclus m'a rappelé que j'avais récemment ajouté le script java JQuery et utilisé des <script src=""/>balises simples pour les inclure.

Lorsque je les ai déplacés de après: par défaut vers avant, le signe_out a recommencé à fonctionner.

J'espère que cela aide quelqu'un.

Greg
la source
5

La plupart des réponses sont partielles. J'ai rencontré ce problème à plusieurs reprises. Deux choses doivent être abordées:

<%= link_to(t('logout'), destroy_user_session_path, :method => :delete) %>

la méthode de suppression doit être spécifiée

Puis imaginez utilise jquery, vous devez donc les charger

   <%= javascript_include_tag "myDirectiveJSfile" %> 

et assurez-vous que les DEUX jquery et jquery-ujs sont spécifiés dans votre myDirectiveJSfile.js

//= require jquery
//= require jquery_ujs
Jérôme
la source
5

N'oubliez pas d'inclure la ligne suivante dans votre application.js (Rails 3)

//= require_self
//= require jquery
//= require jquery_ujs

Inclure jquery_ujsdans mon application rails et ça marche maintenant.

The Lazy Log
la source
4

Si vous utilisez HTTPS avec devise , il se brisera si votre lien de déconnexion est vers la version non sécurisée. À l'arrière, il redirige vers la version sécurisée. Cette redirection est un GET, ce qui provoque le problème.

Assurez-vous que votre lien utilise HTTPS. Vous pouvez le forcer avec protocol: "https"dans votre assistant d'URL (assurez-vous d'utiliser l'aide d'URL et non l'aide de chemin).

<%= link_to "Sign out", destroy_user_session_url(protocol: "https"), method: :delete %>
Tyler Collier
la source
4
  devise_for :users
  devise_scope :user do
    get '/users/sign_out' => 'devise/sessions#destroy'
  end
moment dipolaire
la source
3

Le problème commence avec les rails 3.1 ... /app/assets/javascript/recherchez simplement application.js.

Si le fichier n'existe pas, créez un fichier avec ce nom, je ne sais pas pourquoi mon fichier disparaît ou n'a jamais été créé "rails new app"....

Ce fichier est l'instance de jquery....

rome3ro
la source
3

Beaucoup de solutions sont là. mais surtout l'utiliser,

<%= link_to 'Sign out', destroy_user_session_path, method: :delete %>

ou config devise.rb avec la bonne méthode sign_out

Dans devise.rb

config.sign_out_via = :delete ( or  :get which u like to use.) 
Jon Snow
la source
3

utilisation :getet :deleteméthode pour votre chemin:

devise_scope :user do
  match '/users/sign_out' => 'devise/sessions#destroy', :as => :destroy_user_session, via: [:get, :delete]
end
Zakaria
la source
Remarque: il doit y avoir le devise_for: les utilisateurs doivent être déclarés séparément. voir la réponse de dipole_moment.
Sites Web Taylored
2

Dans vos routes.rb:

 devise_for :users do
    get '/sign_out' => 'devise/sessions#destroy'
    get '/log_in' => 'devise/sessions#new'
    get '/log_out' => 'devise/sessions#destroy'
    get '/sign_up' => 'devise/registrations#new'
    get '/edit_profile' => 'devise/registrations#edit'
 end

et dans votre application.html.erb:

<%if user_signed_in?%>
          <li><%= link_to "Sign_out", sign_out_path %></li>
<% end %>
Matz Heri
la source
1
La syntaxe est maintenant: devise_for: utilisateurs, puis le get doit être placé dans devise_scope: user do REMARQUE: singulier: utilisateur pour devise_scope
Sites Web Taylored
2

C'est ce que j'ai fait (avec Rails 3.0 et Devise 1.4.2):

  1. Assurez-vous que votre page charge rails.js
  2. Utilisez ce paramètre: 'data-method' => 'delete'
  3. Bonne idée d'ajouter ce paramètre:: rel => 'nofollow'
Larry
la source
1

Vérifiez si votre routes.rb a une "ressource: utilisateurs" avant un "devise_for: utilisateurs" puis essayez de les échanger:

  1. Travaux

    • devise_for: utilisateurs
    • ressources: utilisateurs
  2. Échoue

    • ressources: utilisateurs
    • devise_for: utilisateurs
Charles Magid
la source
1

la ':method => :delete« de la page est » data-method="delete"' de sorte que votre page doit avoir jquery_ujs.js, il présentera lien avec la méthode méthode supprime pas get

user1599712
la source
1

Je sais que c'est une vieille question basée sur Rails 3 mais je viens de la rencontrer et de la résoudre sur Rails 4.0.4. Alors j'ai pensé que je pourrais expliquer comment je l'ai corrigé pour toute personne rencontrant ce problème avec cette version. Votre kilométrage peut varier, mais voici ce qui a fonctionné pour moi.

Assurez-vous d'abord que les gemmes sont installées et exécutez l'installation de l'ensemble.

gem 'jquery-rails'

gem 'turbolinks'

gem 'jquery-turbolinks'

Dans application.js, vérifiez que tout est requis comme ci-dessous.

Méfiez-vous si ce problème : c'est //= require jquery.turbolinkset non//= require jquery-turbolinks

//= require jquery
//= require jquery_ujs
//= require jquery.turbolinks
//= require turbolinks
//= require_tree .

Ensuite, ajoutez les liens appropriés dans l'en-tête de application.html.erb.

<%= javascript_include_tag  "application", "data-turbolinks-track" => true %>
<%= javascript_include_tag :defaults %>

Il semble y avoir de nombreuses variantes sur la façon d'implémenter la méthode de suppression qui, je suppose, dépend de la version de Rails que vous utilisez. C'est la deletesyntaxe que j'ai utilisée.

<p><%= link_to "Sign Out", destroy_user_session_path, :method => 'delete' %></p>

J'espère que cela aidera quelqu'un à sortir de ce trou très frustrant!

mikeym
la source
0

En général, lorsque vous obtenez "Aucune correspondance de route" mais que vous pensez avoir défini cette route, revérifiez la méthode du verbe / demande http (que ce soit pour obtenir, mettre, publier, supprimer, etc.) pour cette route .

Si vous exécutez des itinéraires de râteau, vous verrez la méthode attendue et vous pouvez la comparer avec le journal des demandes.

Muntasim
la source