Ninguna ruta coincide con "/ users / sign_out" idear rieles 3

386

Instalé el dispositivo en mi aplicación y apliqué lo siguiente en mi application.html.erbarchivo:

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

Corrí rake routesy confirmó que todas las rutas son válidas.

Además, en mi routes.rbarchivo tengo devise_for :usersy root :to => "home#index".

Recibo el siguiente error de enrutamiento al hacer clic en el enlace "Cerrar sesión":

No route matches "/users/sign_out"

¿Alguna idea de lo que está causando el error?

vich
fuente
1
¿Reiniciaste tu aplicación después de agregar las rutas? Los cambios de ruta solo se hacen efectivos al inicio.
Thilo-Alexander Ginkel
2
Si. Solo lo hice nuevamente para estar a salvo. Además, leí en otro lugar de Stack que podría ser un problema que la gema de diseño más reciente no sea compatible con Rails 3.0.3, así que intenté cambiar mi gema de diseño de 1.4.2 a gem 'devise', :git => 'git://github.com/plataformatec/devise.git'. Sin embargo, eso no hizo nada.
vich
¿Cambiar la entrada del Gemfile no te daría una versión cada vez más nueva de Devise? ¿Has intentado especificar un número de versión inferior?
Leo Cassarani
Podría publicar su archivo routes.rb
Felix
1
La segunda respuesta de Jessie a continuación funcionó perfectamente.
vich

Respuestas:

568

Creo que la ruta para cerrar sesión es un DELETEmétodo. Esto significa que su enlace de cierre de sesión debe tener este aspecto:

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

El tuyo no incluye la :method => :deleteparte. Además, tenga en cuenta que para que esto funcione también debe incluirlo <%= javascript_include_tag :defaults %>en su archivo de diseño ( application.html.erb).

Jessie Dedecker
fuente
3
Puedo decir con seguridad que nunca tuve que hacer eso en ninguna de mis aplicaciones de Rails. link_to "Sign out", destroy_user_session_pathsiempre ha sido lo suficientemente bueno para mí.
Leo Cassarani
8
Hice la prueba y me funciona. No olvides que las cosas cambian de una versión a otra (ya sea en Rails o Devise). Además, cerrar sesión es un comportamiento de cambio de estado que no debe hacerse utilizando métodos GET (en mi humilde opinión).
Jessie Dedecker
23
Para obtener más información, la justificación de por qué esto se cambió en la última versión de Devise se describe aquí y aquí .
Jessie Dedecker
66
Me encontré con este mismo problema y la sugerencia de Jessie funcionó para mí. Espero que cualquiera que esté atravesando el railscast del dispositivo finalmente termine aquí debido a este cambio ...
johnnygoodman
2
También puede escribir esto en su consola web para probarlo $("<a href='/users/sign_out' data-method='delete'>Sign out</a>").appendTo('body');, si jQuery está cargado en la página.
mraaroncruz
133

Cambié esta línea en devise.rb:

config.sign_out_via = :delete

a

config.sign_out_via = :get

y comenzó a funcionar para mí

kitdesai
fuente
22
La forma en que se hizo antes era cerrar sesión usando "GET / users / sign_out", pero lo cambiaron a "DELETE" para hacerlo más RESTful. El autor explicó que un GET no debería realizar cambios en el servidor, como cerrar sesión.
Jonathan Allard
2
Esto funcionó para mí. Si bien aprecio que no es una práctica recomendada, las otras respuestas fallaron. No puedo ver por qué !!
Mild Fuzz
8
También es posible utilizar una matriz si desea admitir varios métodos. Por ejemplo: config.sign_out_via = [ :post, :delete ]o devise_for :users, :sign_out_via => [ :post, :delete ], como se describe en devise / rails / routes.rb .
Hosam Aly
2
No usaría una solicitud GET para cerrar sesión, ya que abre al usuario a un ataque XSRF. (Hacker crea un sitio web con una etiqueta de imagen con src = " foo.com/users/sign_out ", el usuario lo visita y se desconecta).
Ryan Doherty
1
@RyanDoherty Id No me equivoco, XSRF todavía es posible (el atacante solo tiene que usar un formulario con action = "DELETE" en la URL de destino, luego enviarlo automáticamente en la carga de la página).
Maël Nison
60

Probablemente no haya incluido el archivo jquery_ujs javascript. Asegúrese de estar utilizando la última versión de jquery-ujs: https://github.com/rails/jquery-ujs y los últimos archivos disponibles:

rails generate jquery:install

Usted debe no tener ningún archivo más rails.js. Si lo hace, probablemente esté desactualizado. Asegúrese también de que este archivo esté cargado con los valores predeterminados, en config / application.rb

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

(Una vez más, usted debe no tener archivo rails.js aquí). Finalmente, agregue el enlace como se documenta en Devise wiki (estilo haml):

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

Y todo estará bien.

Gravis
fuente
8
Tenía: method => 'delete' en mi link_to, el problema era que jquery_ujs no estaba incluido, esta solución resolvió mi problema. Recuerde poner gemas 'jquery-rails' en su archivo de gemas.
Rob Bazinet
2
Gracias, esto funcionó para mí. En lugar de usar los valores predeterminados, también puede usarjavascript_include_tag "jquery_ujs"
Bnicholas
Buena captura, gracias! Estoy usando require.js para cargar archivos de forma asincrónica y olvidé requerir jquery_ujs.
Dan Fairaizl
Asumí que la "u" significaba sin comprimir y eliminé esta línea application.js. Mala suposición, supongo. Gracias.
Jeff
Este problema surgió (en mi aplicación basada en el dispositivo número 100) después de cambiar twitter bootstrap de less a sass y olvidé agregar nuevamente // / require jquery_ujs en mi application.js.
Joe
31

La capacidad de hacer que el enlace Cerrar sesión sea una llamada BORRAR RESTful requiere un atributo html data-method = "delete"utilizando el código rails = link_to('Logout', destroy_user_session_path, :method => :delete).

Sin embargo, si no tiene la gema jquery-ujsinstalada o no está llamando al javascript resultante en su application.html a través de = javascript_include_tag "application", la respuesta se enviará como una solicitud GET y la ruta fallará.

Tiene algunas opciones si no desea usar jquery-ujso no puede encontrar una manera de hacerlo funcionar:

  1. Cambiar config.sign_out_viaa igual :getdentro devise.rb(no recomendado, ya que DELETE es la consulta RESTful apropiada)
  2. O cambie link_toa = button_to('Logout', destroy_user_session_path, :method => :delete). Con button_toRails hará el trabajo pesado al hacer la llamada ELIMINAR adecuada. Luego puede diseñar el botón para que se vea como un enlace si lo desea.
Will Nathan
fuente
El cambio de link_to a button_to funcionó para mí, pero realmente no entiendo por qué. ¿Qué cambió exactamente aparte del html / css?
Spyros Mandekis
1
Tiene que ver con los rails 'magic' que genera automáticamente html a partir de funciones como button_to y link_to. Sucede que la magia de los rieles para button_to especifica la llamada RESTful DELETE correcta y link_to no. Si tuviera que adivinar, diría que la razón es que los elementos del botón html pueden manejar una llamada DELETE (o agruparse con un campo oculto que especifica la acción) mientras que los enlaces regulares no pueden.
Will Nathan
Gracias por esto. Configuré mi aplicación para manejar jquery manualmente, por lo que no tenía jquery-ujs. Instalar con bower o bundler e incluir la línea adecuada para la canalización de activos soluciona el problema.
jrhorn424
1
Esta me parece la solución más segura y portátil.
Acerca de button_to, Rails genera un formpara toda la acción. Es por eso que es posible usar el :deletemétodo con button_toy no con link_to, solo vea el HTML generado.
Fernando Fabreti
25

Intente agregar una nueva ruta para idear / sesiones # destruir y vincular a eso. P.ej:

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

ver:

<%= link_to "Logout", logout_path %>
Kevin Tsoi
fuente
Obteniendo el mismo error que mmichael. Esta prueba anterior funciona para mí.
rtfminc
1
También tuve el mismo error que mmichael. La solución anterior funcionará, pero no es así como se supone que se debe solucionar. Las rutas predeterminadas en Devise ya incluyen la ruta de cierre de sesión como método DELETE. Normalmente no debería necesitar cambiar las rutas predeterminadas. Es por eso que puede solucionarlo simplemente agregando un parámetro separado a la link_tollamada, como se describe en la otra respuesta.
Jessie Dedecker
No tiene que agregar una ruta al archivo route.rb, devise le permite cambiar el método en devise.rb que se encuentra en el directorio / confit / initializers /.
Travis Pessetto
66
Nunca tenga la ruta de cierre de sesión como GET.
Jagira
@Jagira ¿por qué? ¿Por qué no tanto ELIMINAR como OBTENER?
hrdwdmrbl
14

Úselo en su archivo routes.rb:

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

Tuve el mismo problema con rails 3.1.0, y resolví agregar en el archivo las siguientes líneas:

app/assets/javascripts/application.js
//= require_tree
//= require jquery
//= require jquery_ujs
gringo
fuente
Si usa Bower, intente // = requiera jquery-ujs.
monteirobrena
10

Con una excepción, la respuesta de Jessie funcionó para mí:

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

cambio:

:delete

... a:

'delete'

Entonces el código que funcionó para mí es:

<%= link_to "Sign out", destroy_user_session_path, :method => 'delete' %>
Galen
fuente
Gracias por publicar este fragmento de código, sign_out funciona para mí ahora.
buk
9

Muchas respuestas a la pregunta ya. Para mí, el problema era doble:

  1. cuando amplío mis rutas:

    devise_for :users do 
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  2. Estaba recibiendo una advertencia de que esto se depreciaba, así que lo reemplacé con:

    devise_scope :users do
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  3. Pensé que eliminaría mi jQuery. Mala elección. Devise está utilizando jQuery para "falsificar" la solicitud DELETE y enviarla como GET. Por lo tanto, necesitas:

    //= require jquery
    //= require jquery_ujs
  4. y, por supuesto, el mismo enlace que muchos mencionados anteriormente:

    <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
Lukasz Muzyka
fuente
se puede explicar tercera point..i fue víctima de ella y quiero entenderlo más
Rahul Dess
1
Ciertamente. Su sitio web realmente no está enviando ninguna solicitud ELIMINAR. Francamente, solo usará GET y POST. Debido a que en la comunidad de Rails se ha acordado que (por buenas razones) queremos eliminar registros al enviar la solicitud DELETE, debemos usar un pequeño truco. Cuando en su ERB especifique el método:: delete rails lo convertirá en una etiqueta HTML5: data-method = "delete" y lo enviará como GET. Ahora, aquí es donde entran en juego jQuery-ujs y jQuery. Permiten que la aplicación reconozca que esto es lo que está haciendo. Para que su solicitud pueda coincidir con la acción del controlador.
Lukasz Muzyka
sin esas gemas, esto no funcionará. Por supuesto, puede cambiar la configuración de idear (en el dispositivo de inicialización) y pedirle que use GET en lugar de DELETE.
Lukasz Muzyka
7

Añadir:

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

Use estas etiquetas link_to

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

  or

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

En rutas agregar:

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

Otra opción es configurar el cierre de sesión para que sea GET en lugar de DELETE, puede hacerlo agregando la siguiente línea en /config/initializers/devise.rb

config.sign_out_via = :get

Pero como Steve Klabnik escribió en su blog (http://blog.steveklabnik.com/2011/12/11/devise-actioncontroller-routingerror-no-route-matches-get-slash-users-slash-sign-out.html ) intenta usar DELETE debido a la semántica de este método.

Rodrigo Flores
fuente
Solo esta respuesta funcionó para mí para Devise 3.5.1 y Rails 4.2.3
sagar junnarkar
No olvides reiniciar el servidor :)
jackmin
6

Si está utilizando Rails 3.1, asegúrese de que su cierre de sesión application.html.erb se vea así:

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

Y que su línea de inclusión de JavaScript se parezca a la siguiente

<%= javascript_include_tag 'application' %>

Supongo que algunas gemas sobrescriben la nueva estructura de la ubicación default.js.

StlTenny
fuente
¡Gracias! ¡Esto me estaba volviendo loco!
Dorian
5

Compruébalo con el código fuente en github:

https://github.com/plataformatec/devise/commit/adb127bb3e3b334cba903db2c21710e8c41c2b40#lib/generators/templates/devise.rb (fecha: 27 de junio de 2011)

  • # El método HTTP predeterminado utilizado para cerrar sesión en un recurso. El valor predeterminado es: get. 188
  • # config.sign_out_via =: obtener 187
  • # El método HTTP predeterminado utilizado para cerrar sesión en un recurso. El valor predeterminado es: eliminar. 188
  • config.sign_out_via =: eliminar
Shane
fuente
5

Bueno, chicos, para mí solo fue eliminar el: método =>: eliminar

<%= link_to('Sign out', destroy_user_session_path) %>
soñador
fuente
5

Esto significa que no ha generado los archivos jquery después de haber instalado la gema jquery-rails. Entonces primero necesitas generarlo.

rails generate devise:install

Primera opción:

Esto significa que debes cambiar la siguiente línea en /config/initializers/devise.rb

config.sign_out_via =: eliminar a config.sign_out_via =: obtener

Segunda opción:

Sólo cambia esta línea <%= link_to "Sign out", destroy_user_session_path %>a <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>en el archivo de vista.

Por :method => :deletelo general, no está escrito por defecto.

Deepak Lamichhane
fuente
5

Quiero agregar a esto a pesar de que es un poco viejo.

el enlace "sign_out" no funcionó, a pesar de tener: method =>: delete.

El comentario que indica que <%= javascript_include_tag :defaults %>debe incluirse me recordó que recientemente agregué el script Java JQuery y usé <script src=""/>etiquetas simples para incluirlos.

Cuando los moví después de: el valor predeterminado es antes, el inicio de sesión comenzó a funcionar nuevamente.

Esperemos que esto ayude a alguien.

Greg
fuente
5

La mayoría de las respuestas son parciales. He tocado este problema muchas veces. Deben abordarse dos cosas:

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

el método de eliminación debe especificarse

Luego, crea jquery, por lo que debes cargar esos

   <%= javascript_include_tag "myDirectiveJSfile" %> 

y asegúrese de que AMBOS jquery y jquery-ujs estén especificados en su myDirectiveJSfile.js

//= require jquery
//= require jquery_ujs
Jerome
fuente
5

No olvide incluir la siguiente línea en su application.js (Rails 3)

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

Incluir jquery_ujsen mi aplicación de rieles y funciona ahora.

The Lazy Log
fuente
4

Si está utilizando HTTPS con idear , se romperá si su enlace de cierre de sesión es a la versión no segura. En el back-end, redirige a la versión segura. Esa redirección es un GET, que causa el problema.

Asegúrese de que su enlace use HTTPS. Puede forzarlo protocol: "https"en su asistente de URL (asegúrese de usar el asistente de URL y no el asistente de ruta).

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

El problema comienza con los rieles 3.1 ... /app/assets/javascript/solo busque application.js.

Si el archivo no existe, cree un archivo con ese nombre, no sé por qué mi archivo desaparece o nunca se creó "rails new app"....

Ese archivo es la instancia para jquery....

rome3ro
fuente
3

Muchas soluciones están ahí. pero sobre todo usa esto,

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

o config devise.rb con el método apropiado de sign_out

En devise.rb

config.sign_out_via = :delete ( or  :get which u like to use.) 
Jon nieve
fuente
3

uso :gety :deletemétodo para su camino:

devise_scope :user do
  match '/users/sign_out' => 'devise/sessions#destroy', :as => :destroy_user_session, via: [:get, :delete]
end
Zakaria
fuente
Nota: debe haber la idea_para: usuarios declarados por separado de esto. ver la respuesta de dipole_moment.
Sitios web Taylored
2

En su route.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

y en su application.html.erb:

<%if user_signed_in?%>
          <li><%= link_to "Sign_out", sign_out_path %></li>
<% end %>
Matz Heri
fuente
1
La sintaxis ahora es: devise_for: users, entonces los gets deben ponerse en devise_scope: user do NOTA: singular: user for devise_scope
Sitios web de Taylored
2

Esto es lo que hice (con Rails 3.0 y Devise 1.4.2):

  1. Asegúrese de que su página cargue rails.js
  2. Use este parámetro: 'data-method' => 'delete'
  3. Buena idea agregar este parámetro:: rel => 'nofollow'
Larry
fuente
1

Vea si su route.rb tiene un "recurso: usuarios" antes de un "dispositivo_para: usuarios", luego intente intercambiarlos:

  1. Trabajos

    • idear_para: usuarios
    • recursos: usuarios
  2. Falla

    • recursos: usuarios
    • idear_para: usuarios
Charles Magid
fuente
1

el ':method => :delete'en la página es' data-method="delete"', por lo que su página debe tener jquery_ujs.js, enviará un enlace con el método eliminar, no el método obtener

usuario1599712
fuente
1

Sé que esta es una vieja pregunta basada en Rails 3, pero acabo de encontrarla y la resolví en Rails 4.0.4. Así que pensé en explicar cómo lo solucioné para cualquiera que encuentre este problema con esta versión. Su kilometraje puede variar, pero esto es lo que funcionó para mí.

Primero asegúrese de tener las gemas instaladas y ejecute la instalación del paquete.

gem 'jquery-rails'

gem 'turbolinks'

gem 'jquery-turbolinks'

En application.js verifique que todo se requiera como a continuación.

Tenga cuidado si esto tiene : es //= require jquery.turbolinksy no//= require jquery-turbolinks

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

A continuación, agregue los enlaces apropiados en el encabezado de application.html.erb.

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

Parece que hay muchas variaciones sobre cómo implementar el método de eliminación, que supongo que depende de la versión de Rails que esté utilizando. Esta es la deletesintaxis que utilicé.

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

¡Espero que eso ayude a sacar a alguien de este agujero muy frustrante!

mikeym
fuente
0

En general, cuando obtiene "No hay coincidencias de ruta" pero cree que tiene esa ruta definida, luego verifique dos veces el método de verbo / solicitud http (ya sea get, put, post, delete, etc.) para esa ruta .

Si ejecuta rutas de rastrillo, verá el método esperado y podrá compararlo con el registro de solicitudes.

Muntasim
fuente