Keine Route stimmt mit den Schienen 3 / users / sign_out überein. 3


386

Ich habe devise auf meiner App installiert und Folgendes in meine application.html.erbDatei übernommen:

<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>

Ich lief rake routesund bestätigte, dass alle Routen gültig sind.

Auch in meiner routes.rbDatei habe ich devise_for :usersund root :to => "home#index".

Beim Klicken auf den Link "Abmelden" wird der folgende Routing-Fehler angezeigt:

No route matches "/users/sign_out"

Irgendwelche Ideen, was den Fehler verursacht?


1
Haben Sie Ihre App nach dem Hinzufügen der Routen neu gestartet? Routenänderungen werden erst beim Start wirksam.
Thilo-Alexander Ginkel

2
Ja. Hab es einfach nochmal gemacht, um sicher zu gehen. Außerdem habe ich irgendwo anders auf Stack gelesen, dass es ein Problem sein könnte, wenn das neueste Gerätedelstein nicht mit Rails 3.0.3 kompatibel ist, also habe ich versucht, mein Gerätedelstein von 1.4.2 auf 1.4.2 zu ändern gem 'devise', :git => 'git://github.com/plataformatec/devise.git'. Das hat aber nichts gebracht.
Vich

Würden Sie durch Ändern des Eintrags in der Gemfile nicht einfach eine immer neuere Version von Devise erhalten? Haben Sie versucht, eine niedrigere Versionsnummer anzugeben?
Leo Cassarani

Könnten Sie Ihre route.rb-Datei veröffentlichen
felix

1
Die zweite Antwort von Jessie unten hat perfekt funktioniert.
Vich

Antworten:


568

Ich denke, der Weg zum Abmelden ist eine DELETEMethode. Dies bedeutet, dass Ihr Abmeldelink folgendermaßen aussehen muss:

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

Ihr Teil ist nicht enthalten :method => :delete. Bitte beachten Sie auch, dass Sie dies auch einschließen müssen, damit dies funktioniert<%= javascript_include_tag :defaults %> in Ihre Layoutdatei ( application.html.erb) aufnehmen .


3
Ich kann mit Sicherheit sagen, dass ich das in keiner meiner Rails-Apps tun musste. link_to "Sign out", destroy_user_session_pathwar immer gut genug für mich.
Leo Cassarani

8
Ich habe den Test gemacht und es funktioniert für mich. Vergessen Sie nicht, dass sich die Dinge von einer Version zur anderen ändern (sei es in Rails oder Devise). Außerdem ist das Abmelden ein Verhalten, das den Status ändert und nicht mit GET-Methoden durchgeführt werden sollte (meiner bescheidenen Meinung nach).
Jessie Dedecker

23
Weitere Informationen dazu, warum dies in der neuesten Version von Devise geändert wurde, finden Sie hier und hier .
Jessie Dedecker

6
Ich bin auf dasselbe Problem gestoßen und Jessies Vorschlag hat für mich funktioniert. Ich erwarte, dass jeder, der durch den Railscast läuft, aufgrund dieser Änderung irgendwann hier
landet

2
Sie können dies auch in Ihre Webkonsole eingeben, um es zu testen $("<a href='/users/sign_out' data-method='delete'>Sign out</a>").appendTo('body');- wenn jQuery auf der Seite geladen ist.
mraaroncruz

133

Ich habe diese Zeile in devise.rb geändert:

config.sign_out_via = :delete

zu

config.sign_out_via = :get

und es fing an, für mich zu arbeiten.


22
Die Art und Weise, wie es zuvor gemacht wurde, war, sich mit "GET / users / sign_out" abzumelden, aber sie haben es in "DELETE" geändert, um es RESTful zu machen. Der Autor erklärte, dass ein GET keine Änderungen am Server vornehmen sollte, z. B. das Abmelden.
Jonathan Allard

2
das hat bei mir funktioniert. Obwohl ich zu schätzen weiß, dass dies keine bewährte Methode ist, sind die anderen Antworten fehlgeschlagen. Ich kann nicht sehen warum !!
Mild Fuzz

8
Es ist auch möglich, ein Array zu verwenden, wenn Sie mehrere Methoden unterstützen möchten. Zum Beispiel: config.sign_out_via = [ :post, :delete ]oder devise_for :users, :sign_out_via => [ :post, :delete ], wie in devise / Rails / Routen.rb beschrieben .
Hosam Aly

2
Ich würde keine GET-Anfrage zum Abmelden verwenden, da dies den Benutzer für einen XSRF-Angriff öffnet. (Hacker erstellt eine Website mit einem Image-Tag mit src = " foo.com/users/sign_out ", der Benutzer besucht sie und wird abgemeldet.)
Ryan Doherty

1
@RyanDoherty Id Ich irre mich nicht, XSRF ist immer noch möglich (der Angreifer muss nur ein Formular mit action = "DELETE" für die Ziel-URL verwenden und es dann beim Laden der Seite automatisch senden).
Maël Nison

60

Sie haben wahrscheinlich keine Jquery_ujs-Javascript-Datei hinzugefügt. Stellen Sie sicher, dass Sie die neueste Version von jquery-ujs verwenden: https://github.com/rails/jquery-ujs und die letzten verfügbaren Dateien:

rails generate jquery:install

Sie sollten keine Datei rails.js mehr haben. Wenn Sie dies tun, sind Sie wahrscheinlich veraltet. Stellen Sie sicher, dass auch diese Datei mit den Standardeinstellungen in config / application.rb geladen ist

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

(Auch hier sollten Sie keine Datei rails.js haben). Fügen Sie zum Schluss den Link hinzu, der im Devise-Wiki (Haml-Stil) dokumentiert ist :

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

Und alles wird gut.


8
Ich hatte: method => 'delete' in meinem link_to, das Problem war jquery_ujs nicht enthalten, diese Lösung löste mein Problem. Denken Sie daran, Edelstein-JQuery-Rails in Ihre Gem-Datei einzufügen.
Rob Bazinet

2
Danke, das hat bei mir funktioniert. Anstatt javascript_include_tag "jquery_ujs"
Standardeinstellungen zu

Guter Fang, danke! Ich verwende require.js, um Dateien asynchron zu laden, und habe vergessen, jquery_ujs zu benötigen.
Dan Fairaizl

Ich nahm an, dass das "u" unkomprimiert bedeutet und entfernte diese Zeile aus application.js. Schlechte Annahme, nehme ich an. Vielen Dank.
Jeff

Dieses Problem trat auf (in meiner 100. App-basierten App), nachdem der Twitter-Bootstrap von weniger auf sass geändert wurde, und ich vergaß, die // = require jquery_ujs wieder in meine application.js einzufügen.
Joe

31

Die Möglichkeit, den Logout-Link zu einem DELETE RESTful-Aufruf zu machen, erfordert ein HTML-Attribut data-method = "delete"unter Verwendung des Rails-Codes= link_to('Logout', destroy_user_session_path, :method => :delete) .

Wenn Sie das Gem jedoch nicht jquery-ujsinstalliert haben oder das resultierende Javascript in Ihrer application.html nicht über aufrufen= javascript_include_tag "application" , wird die Antwort als GET-Anforderung gesendet und die Route schlägt fehl.

Sie haben einige Optionen, wenn Sie sie nicht verwenden möchten jquery-ujsoder keine Möglichkeit finden, sie zum Laufen zu bringen:

  1. Wechseln Sie config.sign_out_viazu gleich :getinnerhalbdevise.rb (nicht empfohlen, da DELETE die entsprechende RESTful-Abfrage ist).
  2. ODER Ändern Sie das link_toin = button_to('Logout', destroy_user_session_path, :method => :delete). Mit button_toRails wird das schwere Heben ausgeführt, um den richtigen DELETE-Anruf zu tätigen. Sie können die Schaltfläche dann so gestalten, dass sie wie ein Link aussieht, wenn Sie dies wünschen.

Der Wechsel von link_to zu button_to hat bei mir funktioniert, aber ich verstehe wirklich nicht warum? Was genau hat sich außer HTML / CSS geändert?
Spyros Mandekis

1
Es hat mit der "Magie" der Schienen zu tun, die automatisch HTML aus Funktionen wie button_to und link_to generiert. Es kommt einfach so vor, dass die Rails-Magie für button_to den richtigen RESTful DELETE-Aufruf angibt und link_to nicht. Wenn ich raten müsste, würde ich sagen, dass der Grund dafür ist, dass HTML-Schaltflächenelemente einen DELETE-Aufruf verarbeiten können (oder mit einem versteckten Feld gebündelt werden, das die Aktion angibt), während reguläre Links dies nicht können.
Will Nathan

Danke dafür. Ich habe meine App so eingerichtet, dass sie jquery manuell verarbeitet, sodass ich keine jquery-ujs hatte. Die Installation mit Bower oder Bundler und die Aufnahme der entsprechenden Leitung für die Asset-Pipeline behebt das Problem.
jrhorn424

1
Dies scheint mir die sicherste und tragbarste Lösung zu sein.

Über button_toRails generiert ein formfür die gesamte Aktion. Aus diesem Grund ist es möglich, :deleteMethoden mit button_tound nicht mit zu verwenden link_to. Sehen Sie sich nur den generierten HTML-Code an.
Fernando Fabreti

25

Versuchen Sie, eine neue Route hinzuzufügen, um / session # destroy zu erstellen und eine Verknüpfung dazu herzustellen. Z.B:

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

Aussicht:

<%= link_to "Logout", logout_path %>

Den gleichen Fehler wie mmichael bekommen. Dieser obige Test funktioniert bei mir.
RTFMINC

1
Ich hatte auch den gleichen Fehler wie mmichael. Die obige Lösung wird funktionieren, aber es ist nicht so, wie sie behoben werden soll. Die Standardrouten in Devise enthalten bereits die Abmelderoute als DELETE-Methode. Normalerweise sollten Sie die Standardrouten nicht selbst ändern müssen. Aus diesem Grund können Sie das Problem beheben, indem Sie dem link_toAufruf einfach einen separaten Parameter hinzufügen , wie in der anderen Antwort beschrieben.
Jessie Dedecker

Sie müssen der Datei route.rb keine Route hinzufügen. Mit devise können Sie die Methode in devise.rb ändern, die sich im Verzeichnis / confit / initializers / befindet.
Travis Pessetto

6
Niemals einen Abmeldepfad als GET haben.
Jagira

@ Jagira warum? Warum nicht sowohl LÖSCHEN als auch ERHALTEN?
hrdwdmrbl

14

Verwenden Sie es in Ihrer Datei route.rb:

devise_for :users do
    get '/users/sign_out' => 'devise/sessions#destroy'
end

13

Ich hatte das gleiche Problem mit Rails 3.1.0 und habe das Hinzufügen der folgenden Zeilen in der Datei gelöst:

app/assets/javascripts/application.js
//= require_tree
//= require jquery
//= require jquery_ujs

Wenn Sie bower verwenden, versuchen Sie // = erfordern jquery-ujs.
Monteirobrena

10

Mit einer Ausnahme hat Jessies Antwort für mich funktioniert:

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

Veränderung:

:delete

... zu:

'delete'

Der Code, der für mich funktioniert hat, lautet also:

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

Vielen Dank, dass Sie diesen Code-Ausschnitt veröffentlicht haben. Sign_out funktioniert jetzt für mich.
Buk

9

Viele Antworten auf die Frage schon. Für mich war das Problem zweifach:

  1. wenn ich meine Routen erweitere:

    devise_for :users do 
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  2. Ich wurde gewarnt, dass dies abgeschrieben wird, daher habe ich es ersetzt durch:

    devise_scope :users do
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  3. Ich dachte, ich werde meine jQuery entfernen. Schlechte Wahl. Devise verwendet jQuery, um eine DELETE-Anfrage zu "fälschen" und als GET zu senden. Deshalb müssen Sie:

    //= require jquery
    //= require jquery_ujs
  4. und natürlich derselbe Link wie viele zuvor erwähnte:

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

Kannst du den 3. Punkt erklären? Ich war ein Opfer davon und ich möchte es besser verstehen
Rahul Dess

1
Bestimmt. Ihre Website sendet keine DELETE-Anfragen. Ehrlich gesagt werden nur GET und POST verwendet. Da in der Rails-Community vereinbart wurde, dass wir (aus guten Gründen) Datensätze löschen möchten, wenn wir eine DELETE-Anfrage senden, müssen wir einen kleinen Trick anwenden. Wenn Sie in Ihrem ERB die Methode :: delete Rails angeben, wird diese in das HTML5-Tag konvertiert: data-method = "delete" und als GET gesendet. Hier setzen jQuery-ujs und jQuery an. Sie ermöglichen es der App, zu erkennen, dass Sie dies tun. Damit Ihre Anfrage mit der Controller-Aktion abgeglichen werden kann.
Lukasz Muzyka

Ohne diese Edelsteine ​​wird dies nicht funktionieren. Natürlich können Sie die Einstellungen von devise (im Devise-Initialisierer) ändern und ihn bitten, GET anstelle von DELETE zu verwenden.
Lukasz Muzyka

7

Hinzufügen:

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

Verwenden Sie diese link_to-Tags

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

  or

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

In Routen hinzufügen:

  devise_for :users do
    get '/users/sign_out' => 'devise/sessions#destroy'
  end

7

Eine andere Möglichkeit besteht darin, die Abmeldung als GET statt als DELETE zu konfigurieren. Dazu können Sie die folgende Zeile hinzufügen /config/initializers/devise.rb

config.sign_out_via = :get

Aber wie Steve Klabnik in seinem Blog schrieb (http://blog.steveklabnik.com/2011/12/11/devise-actioncontroller-routingerror-no-route-matches-get-slash-users-slash-sign-out.html) ) versuchen Sie wegen der Semantik dieser Methode, DELETE zu verwenden.


Nur diese Antwort funktionierte für mich für Devise 3.5.1 & Rails
4.2.3

Vergessen Sie nicht, den Server neu zu starten :)
Jackmin

6

Wenn Sie Rails 3.1 verwenden, stellen Sie sicher, dass Ihre application.html.erb-Abmeldung wie folgt aussieht:

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

Und dass Ihre Javascript-Include-Zeile wie folgt aussieht

<%= javascript_include_tag 'application' %>

Ich vermute, dass einige Edelsteine ​​die neue Struktur des Standorts default.js überschreiben.


Vielen Dank! Das hat mich verrückt gemacht!
Dorian


5

Nun, Leute für mich war es nur die: Methode =>: löschen

<%= link_to('Sign out', destroy_user_session_path) %>

5

Dies bedeutet, dass Sie die JQuery-Dateien nach der Installation des JQuery-Rails-Gems nicht generiert haben. Also müssen Sie es zuerst generieren.

rails generate devise:install

Erste Wahl:

Dies bedeutet, dass Sie entweder die folgende Zeile ändern müssen /config/initializers/devise.rb

config.sign_out_via =: löschen zu config.sign_out_via =: get

Zweite Option:

Sie ändern diese Zeile nur <%= link_to "Sign out", destroy_user_session_path %>in <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>der Ansichtsdatei.

Normalerweise :method => :deletewird nicht standardmäßig geschrieben.


5

Ich möchte noch etwas hinzufügen, obwohl es ein bisschen alt ist.

Der Link "sign_out" funktionierte nicht, obwohl: method =>: delete.

Der Kommentar, der angibt, dass enthalten sein <%= javascript_include_tag :defaults %>muss, erinnerte mich daran, dass ich kürzlich ein JQuery-Java-Skript hinzugefügt und einfache <script src=""/>Tags verwendet hatte, um sie einzuschließen .

Als ich sie von nach den Standardeinstellungen von: auf vorher verschoben habe, hat sign_out wieder funktioniert.

Hoffentlich hilft das jemandem.


5

Die meisten Antworten sind teilweise. Ich habe dieses Problem oft getroffen. Zwei Dinge müssen angesprochen werden:

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

Die Löschmethode muss angegeben werden

Dann verwendet devise jquery, sodass Sie diese laden müssen

   <%= javascript_include_tag "myDirectiveJSfile" %> 

und stellen Sie sicher, dass BEIDE jquery und jquery-ujs in Ihrer myDirectiveJSfile.js angegeben sind

//= require jquery
//= require jquery_ujs

5

Vergessen Sie nicht, die folgende Zeile in Ihre application.js (Rails 3) aufzunehmen.

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

Fügen Sie jquery_ujsin meine Rails - Anwendung und es funktioniert jetzt.


4

Wenn Sie HTTPS mit Gerät verwenden , wird es unterbrochen, wenn Ihr Abmeldelink auf die nicht sichere Version verweist. Im Backend wird zur sicheren Version umgeleitet. Diese Weiterleitung ist ein GET, das das Problem verursacht.

Stellen Sie sicher, dass Ihr Link HTTPS verwendet. Sie können es protocol: "https"in Ihrem URL-Helfer erzwingen (stellen Sie sicher, dass Sie den URL-Helfer und nicht den Pfad-Helfer verwenden).

<%= link_to "Sign out", destroy_user_session_url(protocol: "https"), method: :delete %>

4
  devise_for :users
  devise_scope :user do
    get '/users/sign_out' => 'devise/sessions#destroy'
  end

3

Das Problem beginnt mit Schienen 3.1 ... in /app/assets/javascript/ suchen Sie einfach nach application.js.

Wenn die Datei nicht vorhanden ist, erstellen Sie eine Datei mit diesem Namen. Ich weiß nicht, warum meine Datei verschwindet oder nie erstellt wurde "rails new app"....

Diese Datei ist die Instanz für jquery....


3

Es gibt viele Lösungen. aber meistens benutze dies,

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

oder config devise.rb mit der richtigen sign_out-Methode

In devise.rb

config.sign_out_via = :delete ( or  :get which u like to use.) 

3

Verwendung :getund :deleteMethode für Ihren Pfad:

devise_scope :user do
  match '/users/sign_out' => 'devise/sessions#destroy', :as => :destroy_user_session, via: [:get, :delete]
end

Hinweis: Es muss devise_for: users geben, die separat davon deklariert sind. siehe die Antwort von dipole_moment.
Taylored Websites

2

In Ihren Routen.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

und in Ihrer application.html.erb:

<%if user_signed_in?%>
          <li><%= link_to "Sign_out", sign_out_path %></li>
<% end %>

1
Die Syntax lautet jetzt: devise_for: Benutzer, dann müssen die get in devise_scope: user do HINWEIS: Singular: Benutzer für devise_scope
Taylored Web Sites

2

Folgendes habe ich getan (mit Rails 3.0 und Devise 1.4.2):

  1. Stellen Sie sicher, dass Ihre Seite rails.js lädt
  2. Verwenden Sie diesen Parameter: 'Datenmethode' => 'Löschen'
  3. Gute Idee, diesen Parameter hinzuzufügen :: rel => 'nofollow'

1

Überprüfen Sie, ob Ihre route.rb vor einem "devise_for: users" eine "resource: users" hat, und tauschen Sie sie aus:

  1. Funktioniert

    • devise_for: Benutzer
    • Ressourcen: Benutzer
  2. Schlägt fehl

    • Ressourcen: Benutzer
    • devise_for: Benutzer

1

Die ':method => :delete'in Seite ist' data-method="delete"', also muss Ihre Seite jquery_ujs.js haben, es wird ein Link mit der Methode delete not method get gesendet


1

Ich weiß, dass dies eine alte Frage ist, die auf Rails 3 basiert, aber ich bin gerade auf Rails 4.0.4 gestoßen und habe sie gelöst. Also dachte ich, ich würde darüber nachdenken, wie ich es für jeden behoben habe, der auf dieses Problem mit dieser Version stößt. Ihr Kilometerstand kann variieren, aber hier ist, was für mich funktioniert hat.

Stellen Sie zunächst sicher, dass Sie die Edelsteine ​​installiert haben, und führen Sie die Bundle-Installation aus.

gem 'jquery-rails'

gem 'turbolinks'

gem 'jquery-turbolinks'

Überprüfen Sie in application.js, ob alles wie unten angegeben erforderlich ist.

Passen Sie auf, wenn dies ein Fall ist : Es ist //= require jquery.turbolinksund nicht//= require jquery-turbolinks

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

Fügen Sie als Nächstes die entsprechenden Links in die Kopfzeile von application.html.erb ein.

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

Es scheint viele Variationen bei der Implementierung der Löschmethode zu geben, von der ich annehme, dass sie von der von Ihnen verwendeten Rails-Version abhängt. Dies ist die deleteSyntax, die ich verwendet habe.

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

Hoffe, das hilft jemandem aus diesem sehr frustrierenden Loch zu graben!


0

Wenn Sie "Keine Routenübereinstimmungen" erhalten, aber glauben, diese Route definiert zu haben, überprüfen Sie im Allgemeinen die http-Verb- / Anforderungsmethode (ob get, put, post, delete usw.) für diese Route .

Wenn Sie Rake-Routen ausführen, wird die erwartete Methode angezeigt und Sie können diese mit dem Anforderungsprotokoll vergleichen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.