Żadna trasa nie pasuje do „/ users / sign_out” wymyślają szyny 3


386

Zainstalowałem devise w mojej aplikacji i zastosowałem w swoim application.html.erbpliku:

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

Pobiegłem rake routesi potwierdziłem, że wszystkie trasy są prawidłowe.

Ponadto w moim routes.rbpliku mam devise_for :usersi root :to => "home#index".

Po kliknięciu linku „Wyloguj” pojawia się następujący błąd routingu:

No route matches "/users/sign_out"

Wszelkie pomysły, co powoduje błąd?


1
Czy ponownie uruchomiłeś aplikację po dodaniu tras? Zmiany trasy obowiązują dopiero przy uruchomieniu.
— Thilo-Alexander Ginkel

2
Tak. Zrobiłem to jeszcze raz, aby być bezpiecznym. Przeczytałem też gdzie indziej na Stack, że może to być problem z najnowszym klejnotem wymyślonym, który nie jest kompatybilny z Rails 3.0.3, więc spróbowałem zmienić swój wymyślony klejnot z 1.4.2 na gem 'devise', :git => 'git://github.com/plataformatec/devise.git'. To jednak nic nie pomogło.
— vich

Czy zmiana wpisu w Gemfile nie zapewniłaby ci jeszcze nowszej wersji Devise? Czy próbowałeś podać niższy numer wersji?
— Leo Cassarani,

Czy możesz opublikować plik
— trasy.rb

1
Druga odpowiedź Jessie poniżej działała idealnie.
— vich

Odpowiedzi:


568

Myślę, że droga do wylogowania się jest DELETEmetodą. Oznacza to, że link do wylogowania musi wyglądać następująco:

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

Twój nie obejmuje :method => :deleteczęści. Pamiętaj również, że aby to zadziałało, musisz również dołączyć <%= javascript_include_tag :defaults %>do pliku układu ( application.html.erb).


3
Mogę śmiało powiedzieć, że nigdy nie musiałem tego robić w żadnej z moich aplikacji Railsowych. link_to "Sign out", destroy_user_session_pathzawsze było dla mnie wystarczająco dobre.
— Leo Cassarani,

8
Zrobiłem test i to działa dla mnie. Nie zapominaj, że rzeczy zmieniają się z jednej wersji do drugiej (czy to w Railsach, czy Devise). Poza tym wylogowanie jest zachowaniem zmieniającym stan, którego nie należy robić metodami GET (moim skromnym zdaniem).
— Jessie Dedecker,

23
Aby uzyskać więcej informacji, uzasadnienie, dlaczego zostało to zmienione w najnowszej wersji Devise, opisano tutaj i tutaj .
— Jessie Dedecker,

6
Natknąłem się na ten sam problem i sugestia Jessie zadziałała dla mnie. Spodziewam się, że każdy, kto przejdzie przez wymyślony program, ostatecznie skończy tutaj z powodu tej zmiany ...
— johnnygoodman

2
możesz także wpisać to w konsoli internetowej, aby przetestować $("<a href='/users/sign_out' data-method='delete'>Sign out</a>").appendTo('body');- jeśli jQuery jest załadowane na stronie.
— mraaroncruz

133

Zmieniłem tę linię w devise.rb:

config.sign_out_via = :delete

do

config.sign_out_via = :get

i zaczęło to działać dla mnie.


22
Poprzednim sposobem było wylogowanie się za pomocą polecenia „GET / users / sign_out”, ale zmieniono go na „DELETE”, aby uczynić go bardziej RESTful. Autor wyjaśnił, że GET nie powinien wprowadzać zmian na serwerze, takich jak wylogowanie.
— Jonathan Allard

2
to zadziałało dla mnie. Chociaż doceniam, że nie jest to najlepsza praktyka, inne odpowiedzi zawiodły. Nie rozumiem dlaczego !!
— Łagodny Fuzz,

8
Możliwe jest również użycie tablicy, jeśli chcesz obsługiwać wiele metod. Na przykład: config.sign_out_via = [ :post, :delete ]lub devise_for :users, :sign_out_via => [ :post, :delete ], jak opisano w devise / rails / route.rb .
— Hosam Aly

2
Nie użyłbym żądania GET do wylogowania się, ponieważ otwiera ono użytkownika na atak XSRF. (Hacker tworzy witrynę z tagiem graficznym z src = " foo.com/users/sign_out ", użytkownik odwiedza ją i jest wylogowany).
— Ryan Doherty

1
@RyanDoherty Id Nie mylę się, XSRF jest nadal możliwy (atakujący musi tylko użyć formularza z akcją = „USUŃ” na docelowym adresie URL, a następnie automatycznie przesłać go przy ładowaniu strony).
— Maël Nison

60

Prawdopodobnie nie dodałeś pliku javascript jquery_ujs. Upewnij się, że używasz najnowszej wersji jquery-ujs: https://github.com/rails/jquery-ujs i ostatnich dostępnych plików:

rails generate jquery:install

Należy nie mamy żadnych dodatkowych plików rails.js. Jeśli to zrobisz, prawdopodobnie jesteś nieaktualny. Upewnij się, że również ten plik jest załadowany z wartościami domyślnymi, w config / application.rb

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

(Ponownie, to powinno nie mieć plik rails.js tutaj). Na koniec dodaj link zgodnie z dokumentacją na Devise wiki (w stylu haml):

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

I wszystko będzie dobrze.


8
Miałem: method => 'delete' w moim link_to, problem nie obejmował jquery_ujs, to rozwiązanie rozwiązało mój problem. Pamiętaj, aby umieścić klejnot „jquery-szyny” w swoim pliku gem.
— Rob Bazinet

2
Dzięki, że to działało dla mnie. Zamiast domyślnych można również użyćjavascript_include_tag "jquery_ujs"
— Bnicholas,

Dobry połów, dziękuję! Korzystam z pliku wymaganego.js do asynchronicznego ładowania plików i zapomniałem wymagać pliku jquery_ujs.
— Dan Fairaizl

Zakładałem, że „u” oznacza nieskompresowane i usunąłem tę linię application.js. Złe przypuszczenie. Dzięki.
— Jeff

Ten problem pojawił się (w mojej aplikacji opartej na 100. opracowaniu) po zmianie paska startowego twittera z less na sass i zapomniałem dodać z powrotem // = wymagają jquery_ujs do mojej application.js.
— Joe

31

Możliwość ustawienia połączenia Wyloguj jako USUNIĘCIA wywołania RESTful wymaga atrybutu HTML data-method = "delete"za pomocą kodu szyny = link_to('Logout', destroy_user_session_path, :method => :delete).

Jeśli jednak nie masz jquery-ujszainstalowanego klejnotu lub nie wywołujesz wynikowego javascript w = javascript_include_tag "application"pliku application.html przez , odpowiedź zostanie wysłana jako żądanie GET, a trasa się nie powiedzie.

Masz kilka opcji, jeśli nie chcesz używać jquery-ujslub nie możesz znaleźć sposobu, aby to zadziałało:

  1. Zmień config.sign_out_viana równe :getw obrębie devise.rb(niezalecane, ponieważ DELETE jest odpowiednim zapytaniem RESTful)
  2. Lub zmiany link_todo = button_to('Logout', destroy_user_session_path, :method => :delete). Z button_toszynami wykona ciężkie podnoszenie po prawidłowym wywołaniu DELETE. Następnie możesz stylizować przycisk, aby wyglądał jak link, jeśli chcesz.

Zmiana z link_to na button_to zadziałała dla mnie, ale naprawdę nie rozumiem dlaczego? Co dokładnie zmieniło się oprócz html / css?
— Spyros Mandekis

1
Ma to związek z „magią” szyn, która automatycznie generuje HTML z funkcji takich jak button_to i link_to. Zdarza się tak, że magia szyn dla button_to określa prawidłowe wywołanie RESTful DELETE, a link_to nie. Gdybym musiał zgadywać, powiedziałbym, że powodem jest to, że elementy przycisku HTML mogą obsługiwać wywołanie DELETE (lub pakiet z ukrytym polem określającym akcję), podczas gdy zwykłe linki nie.
— Czy Nathan

Dzięki za to. Skonfigurowałem aplikację do ręcznego obsługi jquery, więc nie miałem jquery-ujs. Instalowanie z altaną lub pakietem i dołączenie odpowiedniego wiersza do potoku zasobów rozwiązuje problem.
— jrhorn424

1
Wydaje mi się to najbezpieczniejszym i najbardziej przenośnym rozwiązaniem.

O button_to, Railsy generują formdla całej akcji. Dlatego możliwe jest użycie :deletemetody zi button_tobez link_to, po prostu zobacz wygenerowany HTML.
— Fernando Fabreti

25

Spróbuj dodać nową trasę do opracowania / sesji # zniszczyć i link do niej. Na przykład:

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

widok:

<%= link_to "Logout", logout_path %>

Uzyskanie tego samego błędu co mmichael. Powyższy test działa dla mnie.
— rtfminc

1
Miałem również ten sam błąd co mmichael. Powyższe rozwiązanie będzie działać, ale nie tak powinno być naprawione. Domyślne trasy w Devise zawierają już trasę wylogowania jako metodę DELETE. Zwykle nie trzeba zmieniać samych domyślnych tras. Dlatego możesz to naprawić, dodając osobny parametr do link_towywołania, jak opisano w drugiej odpowiedzi.
— Jessie Dedecker,

Nie musisz dodawać trasy do pliku route.rb, devise pozwala zmienić metodę w devise.rb, która znajduje się w katalogu / confit / initializers /.
— Travis Pessetto

6
Nigdy nie używaj ścieżki wylogowania jako GET.
— Jagira,

@Jagira dlaczego? Dlaczego nie zarówno DELETE, jak i GET?
— hrdwdmrbl

14

Użyj go w pliku route.rb:

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

13

Miałem ten sam problem z szynami 3.1.0 i rozwiązałem dodawanie w pliku następujących wierszy:

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

Jeśli używasz altany, spróbuj // = wymagają jquery-ujs.
— monteirobrena

10

Z jednym wyjątkiem odpowiedź Jessie zadziałała dla mnie:

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

zmiana:

:delete

... do:

'delete'

Więc kod, który zadziałał dla mnie to:

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

Dziękujemy za opublikowanie tego fragmentu kodu, sign_out działa teraz dla mnie.
— buk

9

Wiele odpowiedzi na pytanie już. Dla mnie problem był dwojaki:

  1. kiedy rozwijam swoje trasy:

    devise_for :users do 
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  2. Ostrzegałem mnie, że jest to amortyzowane, więc zastąpiłem go:

    devise_scope :users do
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  3. Myślałem, że usunę moje jQuery. Zły wybór. Devise używa jQuery do „sfałszowania” żądania DELETE i wysłania go jako GET. Dlatego musisz:

    //= require jquery
    //= require jquery_ujs
  4. i oczywiście ten sam link, jak wiele wcześniej wspomnianych:

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

czy możesz wyjaśnić trzeci punkt ... byłem jego ofiarą i chcę to zrozumieć
— Rahul Dess

1
Na pewno. Twoja witryna tak naprawdę nie wysyła żadnych żądań DELETE. Szczerze mówiąc, użyje tylko GET i POST. Ponieważ w społeczności Rails uzgodniono, że (z dobrych powodów) chcemy usunąć rekordy podczas przesyłania żądania DELETE, musimy skorzystać z małej sztuczki. W swoim ERB określasz metodę:: usuń szyny przekonwertuje to na tag HTML5: data-method = "delete" i prześle jako GET. Teraz właśnie tutaj uruchamiają się jQuery-ujs i jQuery. Pozwalają one aplikacji rozpoznać, co robisz. Aby Twoje zapytanie można było dopasować do działania kontrolera.
— Łukasz Muzyka

bez tych klejnotów to nie zadziała. Oczywiście możesz zmienić ustawienia devise (w inicjalizatorze devise) i poprosić go o użycie GET zamiast DELETE.
— Łukasz Muzyka

7

Dodaj:

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

Użyj tych tagów link_to

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

  or

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

W trasach dodaj:

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

7

Inną opcją jest skonfigurowanie wylogowania jako GET zamiast DELETE, możesz to zrobić, dodając następujący wiersz /config/initializers/devise.rb

config.sign_out_via = :get

Ale jak napisał Steve Klabnik na swoim blogu (http://blog.steveklabnik.com/2011/12/11/devise-actioncontroller-routingerror-no-route-matches-get-slash-users-slash-sign-out.html ) spróbuj użyć DELETE z powodu semantyki tej metody.


Tylko ta odpowiedź działała dla mnie w Devise 3.5.1 i Rails 4.2.3
— sagar junnarkar

Nie zapomnij zrestartować serwera :)
— jackmin

6

Jeśli używasz Rails 3.1, upewnij się, że wylogowanie application.html.erb wygląda następująco:

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

I że Twój wiersz JavaScript zawiera następujący wygląd

<%= javascript_include_tag 'application' %>

Domyślam się, że niektóre klejnoty nadpisują nową strukturę domyślnej lokalizacji.js.


Dzięki! Doprowadzało mnie to do szału!
— Dorian


5

Cóż, chłopaki dla mnie to było tylko usunięcie: method =>: delete

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

5

Oznacza to, że nie wygenerowałeś plików jquery po zainstalowaniu klejnotu jquery-rails. Najpierw musisz go wygenerować.

rails generate devise:install

Pierwsza opcja:

Oznacza to, że musisz zmienić następujący wiersz /config/initializers/devise.rb

config.sign_out_via =: usuń do config.sign_out_via =: get

Druga opcja:

Zmieniasz tylko ten wiersz <%= link_to "Sign out", destroy_user_session_path %>na<%= link_to "Sign out", destroy_user_session_path, :method => :delete %> plik widoku.

Zwykle :method => :deletenie jest napisane domyślnie.


5

Chcę to dodać, choć jest trochę stary.

link „sign_out” nie działał, mimo że: method =>: delete.

Komentarz wskazujący, że <%= javascript_include_tag :defaults %>należy to uwzględnić przypomniał mi, że niedawno dodałem skrypt JQuery Java i użyłem prostego<script src=""/> tagów, aby je uwzględnić.

Kiedy przeniosłem je z: domyślnie na wcześniej, wylogowanie znów zaczęło działać.

Mam nadzieję, że to komuś pomaga.


5

Większość odpowiedzi jest częściowa. Dotknąłem tego problemu wiele razy. Należy zająć się dwiema kwestiami:

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

należy usunąć metodę usuwania

Następnie wymyśl użycie jquery, więc musisz je załadować

   <%= javascript_include_tag "myDirectiveJSfile" %> 

i upewnij się, że ZARÓWNO jquery i jquery-ujs są określone w pliku myDirectiveJSfile.js

//= require jquery
//= require jquery_ujs

5

Nie zapomnij dołączyć następującego wiersza do pliku application.js (Rails 3)

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

Dołącz jquery_ujsdo mojej aplikacji railsowej i działa teraz.


4

Jeśli używasz HTTPS z devise , zepsuje się , jeśli link do wylogowania jest w niezabezpieczonej wersji. Z tyłu przekierowuje do bezpiecznej wersji. Przekierowanie to GET, które powoduje problem.

Upewnij się, że Twój link używa HTTPS. Możesz wymusić to protocol: "https"w pomocniku url (upewnij się, że używasz pomocnika url, a nie pomocnika ścieżki).

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


3

Problem zaczyna się od szyn 3.1. /app/assets/javascript/Wystarczy poszukać application.js.

Jeśli plik nie istnieje, utwórz plik o tej nazwie, nie wiem, dlaczego mój plik zniknął lub nigdy nie został utworzony "rails new app"....

Ten plik jest instancją dla jquery....


3

Istnieje wiele rozwiązań. ale najczęściej używają tego,

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

lub config devise.rb z odpowiednią metodą sign_out

W devise.rb

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

3

użyj :geti :deletemetody na swojej ścieżce:

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

Uwaga: musi istnieć devise_for: użytkownicy deklarowani osobno. zobacz odpowiedź z dipole_moment.
— Taylored Web Sites

2

W twoich trasach.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

oraz w application.html.erb:

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

1
Składnia jest teraz: devise_for: users, a następnie get musi zostać umieszczone w devise_scope: user do UWAGA: liczba pojedyncza: użytkownik dla devise_scope
— Web Sites

2

Oto co zrobiłem (z Railsami 3.0 i Devise 1.4.2):

  1. Upewnij się, że strona ładuje plik rails.js
  2. Użyj tego parametru: „data-method” => „delete”
  3. Dobry pomysł, aby dodać ten parametr:: rel => 'nofollow'

1

Sprawdź, czy twoja route.rb ma „zasób: użytkownicy” przed „devise_for: users”, a następnie spróbuj je zamienić:

  1. Pracuje

    • devise_for: users
    • zasoby: użytkownicy
  2. Zawodzi

    • zasoby: użytkownicy
    • devise_for: users

1

':method => :delete„na stronie” data-method="delete"'więc Twoja strona musi mieć jquery_ujs.js, złoży odnośnik metodą metoda usuwania nie dać


1

Wiem, że to stare pytanie oparte na Railsach 3, ale właśnie natknąłem się i rozwiązałem je w Railsach 4.0.4. Pomyślałem więc, że poprawię sposób, w jaki naprawiłem to dla każdego, kto napotka ten problem w tej wersji. Twój przebieg może się różnić, ale oto, co zadziałało dla mnie.

Najpierw upewnij się, że masz zainstalowane klejnoty i uruchom instalację pakietu.

gem 'jquery-rails'

gem 'turbolinks'

gem 'jquery-turbolinks'

W application.js sprawdź, czy wszystko jest wymagane, jak poniżej.

Uważaj, jeśli to masz : to //= require jquery.turbolinksi nie//= require jquery-turbolinks

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

Następnie dodaj odpowiednie linki w nagłówku application.html.erb.

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

Wydaje się, że istnieje wiele odmian sposobu implementacji metody usuwania, która, jak zakładam, zależy od używanej wersji Railsów. To jest deleteskładnia, której użyłem.

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

Mam nadzieję, że pomożesz wykopać kogoś z tej bardzo frustrującej dziury!


0

Zasadniczo, gdy pojawi się komunikat „Brak pasujących tras”, ale wydaje się, że zdefiniowano tę trasę, należy dwukrotnie sprawdzić metodę czasownika / żądania http (czy jest to get, put, post, delete itd.) Dla tej trasy .

Jeśli uruchomisz trasy prowizji, zobaczysz oczekiwaną metodę i możesz ją porównać z dziennikiem żądań.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.