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