Tidak ada rute yang cocok dengan “/ pengguna / sign_out” yang merancang rel 3

386

Saya telah menginstal alat pada aplikasi saya dan menerapkan hal berikut dalam application.html.erbfile saya :

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

Saya berlari rake routesdan memastikan bahwa semua rute itu valid.

Juga, dalam routes.rbfile saya, saya punya devise_for :usersdan root :to => "home#index".

Saya mendapatkan kesalahan perutean berikut saat mengeklik tautan "Keluar":

No route matches "/users/sign_out"

Adakah ide yang menyebabkan kesalahan?

vich
sumber
1
Apakah Anda memulai ulang aplikasi setelah menambahkan rute? Perubahan rute hanya berlaku pada saat startup.
Thilo-Alexander Ginkel
2
Iya. Lakukan lagi untuk aman. Juga, saya membaca di tempat lain di Stack bahwa itu bisa menjadi masalah dengan permata alat terbaru yang tidak kompatibel dengan Rails 3.0.3 jadi saya mencoba mengubah permata alat saya dari 1.4.2 ke gem 'devise', :git => 'git://github.com/plataformatec/devise.git'. Tapi itu tidak melakukan apa pun.
vich
Tidakkah mengubah entri dalam Gemfile hanya memberi Anda versi Devise yang lebih baru? Sudahkah Anda mencoba menentukan nomor versi yang lebih rendah?
Leo Cassarani
Bisakah Anda memposting file routes.rb Anda
felix
1
Jawaban kedua oleh Jessie di bawah ini bekerja dengan sempurna.
vich

Jawaban:

568

Saya pikir rute untuk keluar adalah DELETEmetode. Ini berarti bahwa tautan keluar Anda harus terlihat seperti ini:

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

Milik Anda tidak termasuk :method => :deletebagian. Juga, harap perhatikan bahwa agar ini berfungsi, Anda juga harus memasukkan <%= javascript_include_tag :defaults %>dalam file tata letak Anda ( application.html.erb).

Jessie Dedecker
sumber
3
Saya dapat mengatakan dengan aman bahwa saya belum pernah melakukannya di salah satu aplikasi Rails saya. link_to "Sign out", destroy_user_session_pathselalu cukup baik untukku.
Leo Cassarani
8
Saya melakukan tes dan itu berhasil untuk saya. Jangan lupa bahwa segalanya berubah dari satu versi ke versi lain (baik itu dalam Rails atau Devise). Selain itu, logout adalah perilaku yang mengubah keadaan yang seharusnya tidak dilakukan menggunakan metode GET (menurut pendapat saya).
Jessie Dedecker
23
Untuk informasi lebih lanjut, alasan mengapa ini diubah dalam versi terbaru dari Devise dijelaskan di sini dan di sini .
Jessie Dedecker
6
Saya mengalami masalah yang sama dan saran Jessie bekerja untuk saya. Saya berharap siapa pun yang menjalankan railscast merancang akhirnya berakhir di sini karena perubahan ini ...
johnnygoodman
2
Anda juga dapat mengetik ini di konsol web Anda untuk mengujinya $("<a href='/users/sign_out' data-method='delete'>Sign out</a>").appendTo('body');- jika jQuery dimuat pada halaman.
mraaroncruz
133

Saya mengubah baris ini di devise.rb:

config.sign_out_via = :delete

untuk

config.sign_out_via = :get

dan itu mulai bekerja untuk saya.

kitdesai
sumber
22
Cara itu dilakukan sebelumnya adalah keluar menggunakan "GET / pengguna / sign_out", tetapi mereka mengubahnya menjadi "HAPUS" untuk membuatnya lebih tenang. Penulis menjelaskan bahwa GET tidak boleh membuat perubahan ke server seperti logout.
Jonathan Allard
2
ini bekerja untuk saya. Sementara saya menghargai itu bukan praktik terbaik, jawaban yang lain gagal. Saya tidak mengerti mengapa !!
Mild Fuzz
8
Dimungkinkan juga untuk menggunakan array jika Anda ingin mendukung banyak metode. Misalnya: config.sign_out_via = [ :post, :delete ]atau devise_for :users, :sign_out_via => [ :post, :delete ], seperti yang dijelaskan dalam merancang / rails / routes.rb .
Hosam Aly
2
Saya tidak akan menggunakan permintaan GET untuk keluar karena itu membuka pengguna hingga serangan XSRF. (Peretas membuat situs web dengan tag gambar dengan src = " foo.com/users/sign_out ", pengguna mengunjunginya dan keluar).
Ryan Doherty
1
@RyanDoherty Id Saya tidak salah, XSRF masih mungkin (penyerang hanya perlu menggunakan formulir dengan action = "HAPUS" pada url target, kemudian kirimkan secara otomatis saat memuat halaman).
Maël Nison
60

Anda mungkin tidak memasukkan file javascript jquery_ujs. Pastikan Anda menggunakan versi terbaru jquery-ujs: https://github.com/rails/jquery-ujs dan file terakhir yang tersedia:

rails generate jquery:install

Anda seharusnya tidak memiliki file rails.js lagi. Jika ya, Anda mungkin kedaluwarsa. Pastikan juga file ini dimuat dengan default, di config / application.rb

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

(Sekali lagi, Anda seharusnya tidak memiliki file rails.js di sini). Terakhir, tambahkan tautan seperti yang didokumentasikan pada Devise wiki (haml-style):

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

Dan semuanya akan baik-baik saja.

Gravis
sumber
8
Saya punya: method => 'delete' di link_to saya, masalahnya jquery_ujs tidak termasuk, solusi ini menyelesaikan masalah saya. Ingatlah untuk menaruh 'jquery-rails' permata di gemfile Anda.
Rob Bazinet
2
Terima kasih, ini berhasil untuk saya. Alih-alih menggunakan default, Anda juga dapat menggunakanjavascript_include_tag "jquery_ujs"
Bnicholas
Tangkapan yang bagus, terima kasih! Saya menggunakan require.js untuk memuat file secara tidak sinkron dan lupa membutuhkan jquery_ujs.
Dan Fairaizl
Saya menganggap "kamu" berarti tidak terkompresi dan menghapus baris ini dari application.js. Anggapan yang buruk, saya kira. Terima kasih.
Jeff
Masalah ini terpotong (dalam aplikasi berbasis perangkat ke-100 saya) setelah mengubah bootstrap twitter dari kurang menjadi sass dan saya lupa menambahkan kembali // = memerlukan jquery_ujs ke application.js saya.
Joe
31

Kemampuan untuk membuat tautan Logout sebagai DELETE RESTful call membutuhkan atribut html data-method = "delete"dengan menggunakan kode rails = link_to('Logout', destroy_user_session_path, :method => :delete).

Namun, jika Anda tidak jquery-ujsmenginstal gem atau tidak memanggil javascript yang dihasilkan di application.html via = javascript_include_tag "application", respons akan dikirim sebagai permintaan GET, dan rute akan gagal.

Anda memiliki beberapa opsi jika Anda tidak ingin menggunakan jquery-ujsatau tidak dapat menemukan cara untuk membuatnya berfungsi:

  1. Ubah config.sign_out_viamenjadi sama di :getdalam devise.rb(tidak disarankan, karena DELETE adalah permintaan RESTful yang sesuai)
  2. ATAU Ubah link_toke = button_to('Logout', destroy_user_session_path, :method => :delete). Dengan button_toRails akan melakukan pekerjaan berat untuk membuat panggilan DELETE yang tepat. Anda kemudian dapat menata tombol agar terlihat seperti tautan jika diinginkan.
Will Nathan
sumber
Perubahan dari link_to ke button_to bekerja untuk saya, tetapi saya benar-benar tidak mengerti mengapa? Apa yang sebenarnya berubah selain dari html / css?
Spyros Mandekis
1
Ini ada hubungannya dengan rel 'magic' yang secara otomatis menghasilkan html dari fungsi seperti button_to dan link_to. Kebetulan rails magic untuk button_to menentukan panggilan DELETE RESTful yang tepat dan link_to tidak. Jika saya harus menebak, saya akan mengatakan alasannya adalah bahwa elemen tombol html dapat menangani panggilan DELETE (atau bundel dengan bidang tersembunyi yang menentukan tindakan) sementara tautan biasa tidak bisa.
Will Nathan
Terima kasih untuk ini. Saya mengatur aplikasi saya untuk secara manual menangani jquery, jadi saya tidak punya jquery-ujs. Menginstal dengan bower atau bundler dan termasuk jalur yang sesuai untuk pipa aset memperbaiki masalah.
jrhorn424
1
Menurut saya ini solusi teraman dan paling portabel.
Tentang button_to, Rails menghasilkan a formuntuk seluruh aksi. Itu sebabnya mungkin menggunakan :deletemetode dengan button_todan tidak dengan link_to, lihat saja HTML yang dihasilkan.
Fernando Fabreti
25

Coba tambahkan rute baru untuk menyusun / sesi # hancurkan dan tautkan ke sana. Misalnya:

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

melihat:

<%= link_to "Logout", logout_path %>
Kevin Tsoi
sumber
Mendapatkan kesalahan yang sama dengan mmichael. Tes di atas bekerja untuk saya.
rtfminc
1
Saya juga memiliki kesalahan yang sama dengan mmichael. Solusi di atas akan berfungsi tetapi tidak seharusnya diperbaiki. Rute default di Devise sudah termasuk rute keluar sebagai metode DELETE. Anda biasanya tidak perlu mengubah rute default sendiri. Itu sebabnya Anda dapat memperbaikinya dengan hanya menambahkan parameter terpisah ke link_topanggilan, seperti yang dijelaskan dalam jawaban lainnya.
Jessie Dedecker
Anda tidak perlu menambahkan rute ke fiile route.rb, devise memungkinkan Anda mengubah metode di devise.rb yang ada di direktori / confit / initializers /.
Travis Pessetto
6
Tidak pernah memiliki jalur keluar sebagai DAPATKAN.
Jagira
@ Jagira mengapa? Mengapa tidak DELETE dan GET?
hrdwdmrbl
14

Gunakan itu di file routes.rb Anda:

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

Saya memiliki masalah yang sama dengan rail 3.1.0, dan saya menyelesaikan menambahkan file sebagai berikut:

app/assets/javascripts/application.js
//= require_tree
//= require jquery
//= require jquery_ujs
gringo
sumber
Jika menggunakan bower coba // = membutuhkan jquery-ujs.
monteirobrena
10

Dengan satu pengecualian, jawaban Jessie bekerja untuk saya:

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

perubahan:

:delete

... untuk:

'delete'

Jadi kode yang berfungsi untuk saya adalah:

<%= link_to "Sign out", destroy_user_session_path, :method => 'delete' %>
Galen
sumber
Terima kasih telah memposting potongan kode ini, sign_out berfungsi untuk saya sekarang.
buk
9

Sudah banyak jawaban untuk pertanyaan itu. Bagi saya masalahnya adalah dua kali lipat:

  1. ketika saya memperluas rute saya:

    devise_for :users do 
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  2. Saya mendapat peringatan bahwa ini disusutkan sehingga saya menggantinya dengan:

    devise_scope :users do
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  3. Saya pikir saya akan menghapus jQuery saya. Pilihan yang buruk. Devise menggunakan jQuery untuk "palsu" HAPUS permintaan dan kirim sebagai GET. Karena itu Anda perlu:

    //= require jquery
    //= require jquery_ujs
  4. dan tentu saja tautan yang sama dengan yang disebutkan sebelumnya:

    <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
Lukasz Muzyka
sumber
dapatkah Anda menjelaskan poin ke 3 .. saya adalah korbannya dan saya ingin lebih memahaminya
Rahul Dess
1
Pasti. Situs web Anda tidak benar-benar mengirim permintaan DELETE. Sejujurnya itu hanya akan menggunakan GET dan POST. Karena di komunitas Rails telah disepakati bahwa (untuk alasan yang baik) kami ingin menghapus catatan ketika mengirimkan permintaan DELETE kami perlu menggunakan sedikit trik. Ketika di ERB Anda menentukan metode:: delete rails akan mengubahnya menjadi tag HTML5: data-method = "delete" dan kirimkan sebagai GET. Sekarang, ini adalah tempat jQuery-ujs dan jQuery masuk. Mereka memungkinkan aplikasi mengenali ini yang Anda lakukan. Sehingga permintaan Anda dapat dicocokkan dengan tindakan pengontrol.
Lukasz Muzyka
tanpa permata itu, ini tidak akan berhasil. Tentu saja, Anda dapat mengubah pengaturan alat (dalam merancang alat pendaftar) dan memintanya untuk menggunakan GET bukannya DELETE.
Lukasz Muzyka
7

Menambahkan:

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

Gunakan tag link_to ini

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

  or

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

Dalam rute tambahkan:

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

Opsi lainnya adalah mengonfigurasi logout menjadi GET dan bukannya DELETE, Anda bisa melakukannya dengan menambahkan baris berikut ini /config/initializers/devise.rb

config.sign_out_via = :get

Tetapi seperti yang ditulis Steve Klabnik di blognya (http://blog.steveklabnik.com/2011/12/12/devise-actioncontroller-routingerror-no-route-matches-get-slash-users-slash-sign-out.html ) coba gunakan HAPUS karena semantik dari metode ini.

Rodrigo Flores
sumber
Hanya jawaban ini yang bekerja untuk saya untuk Rancangan 3.5.1 & Rails 4.2.3
sagar junnarkar
Jangan lupa restart server :)
jackmin
6

Jika Anda menggunakan Rails 3.1, pastikan application.html.erb Anda keluar seperti:

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

Dan javascript Anda termasuk baris seperti berikut ini

<%= javascript_include_tag 'application' %>

Dugaan saya adalah bahwa beberapa permata menimpa struktur baru dari lokasi default.js.

StTTenny
sumber
Terima kasih! Ini membuatku gila!
Dorian
5

Nah, bagi saya itu hanya menghapus: method =>: delete

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

Ini berarti Anda belum membuat file jquery setelah Anda menginstal gem jquery-rails. Jadi pertama-tama Anda harus membuatnya.

rails generate devise:install

Pilihan pertama:

Ini berarti Anda harus mengubah baris berikut /config/initializers/devise.rb

config.sign_out_via =: delete to config.sign_out_via =: get

Opsi kedua:

Anda hanya mengubah baris ini <%= link_to "Sign out", destroy_user_session_path %>menjadi <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>pada file tampilan.

Biasanya :method => :deletetidak ditulis secara default.

Deepak Lamichhane
sumber
5

Saya ingin menambahkan ini meskipun agak lama.

tautan "sign_out" tidak berfungsi, meskipun memiliki: method =>: delete.

Komentar yang menunjukkan bahwa <%= javascript_include_tag :defaults %>harus dimasukkan mengingatkan saya, saya baru saja menambahkan skrip java JQuery dan menggunakan <script src=""/>tag sederhana untuk memasukkan mereka.

Ketika saya memindahkan mereka dari setelah: default ke sebelumnya, sign_out mulai bekerja kembali.

Semoga ini bisa membantu seseorang.

Greg
sumber
5

Sebagian besar jawaban sebagian. Saya telah mengenai masalah ini berkali-kali. Dua hal yang perlu diatasi:

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

metode hapus perlu ditentukan

Kemudian rancang menggunakan jquery, jadi Anda harus memuatnya

   <%= javascript_include_tag "myDirectiveJSfile" %> 

dan memastikan bahwa KEDUA jquery dan jquery-ujs ditentukan dalam myDirectiveJSfile.js Anda

//= require jquery
//= require jquery_ujs
Jerome
sumber
5

Jangan lupa untuk memasukkan baris berikut di application.js Anda (Rails 3)

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

Sertakan jquery_ujske dalam aplikasi rel saya dan berfungsi sekarang.

Log Malas
sumber
4

Jika Anda menggunakan HTTPS dengan alat , itu akan rusak jika tautan keluar Anda ke versi yang tidak aman. Di ujung belakang, itu dialihkan ke versi yang aman. Redirect itu adalah GET, yang menyebabkan masalah.

Pastikan tautan Anda menggunakan HTTPS. Anda dapat memaksanya dengan protocol: "https"di helper url Anda (pastikan Anda menggunakan helper url dan bukan helper path).

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

Masalahnya dimulai dengan rel 3.1 ... /app/assets/javascript/hanya dalam mencari application.js.

Jika file tidak ada, buat file dengan nama itu. Saya tidak tahu mengapa file saya hilang atau tidak pernah dibuat "rails new app"....

File itu adalah contoh untuk jquery....

rome3ro
sumber
3

Ada banyak solusi di sana. tetapi sebagian besar menggunakan ini,

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

atau config devise.rb dengan metode sign_out yang tepat

Dalam merancang.rb

config.sign_out_via = :delete ( or  :get which u like to use.) 
jon snow
sumber
3

gunakan :getdan :deletemetode untuk jalur Anda:

devise_scope :user do
  match '/users/sign_out' => 'devise/sessions#destroy', :as => :destroy_user_session, via: [:get, :delete]
end
Zakaria
sumber
Catatan: harus ada devise_for: pengguna dideklarasikan secara terpisah dari ini. lihat jawaban dari dipole_moment.
Situs Web Taylored
2

Di route.rb Anda:

 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

dan di application.html.erb Anda:

<%if user_signed_in?%>
          <li><%= link_to "Sign_out", sign_out_path %></li>
<% end %>
Matz Heri
sumber
1
Sintaksnya sekarang: devise_for: pengguna maka get harus dimasukkan ke dalam devise_scope: user do CATATAN: singular: user untuk devise_scope
Situs Web Taylored
2

Inilah yang saya lakukan (dengan Rails 3.0 dan Rancangan 1.4.2):

  1. Pastikan halaman Anda memuat rails.js
  2. Gunakan param ini: 'data-method' => 'delete'
  3. Ide bagus untuk menambahkan param ini:: rel => 'nofollow'
Larry
sumber
1

Lihat apakah route.rb Anda memiliki "sumber daya: pengguna" sebelum "devise_for: users" lalu coba menukar mereka:

  1. Bekerja

    • devise_for: pengguna
    • sumber daya: pengguna
  2. Gagal

    • sumber daya: pengguna
    • devise_for: pengguna
Charles Magid
sumber
1

halaman ':method => :delete'in is' data-method="delete"'sehingga halaman Anda harus memiliki jquery_ujs.js, itu akan mengirimkan tautan dengan metode delete not method get

pengguna1599712
sumber
1

Saya tahu ini adalah pertanyaan lama berdasarkan Rails 3 tapi saya hanya berlari dan menyelesaikannya di Rails 4.0.4. Jadi saya pikir saya akan membahas bagaimana saya memperbaikinya bagi siapa saja yang mengalami masalah dengan versi ini. Jarak tempuh Anda mungkin beragam, tetapi inilah yang bekerja untuk saya.

Pertama-tama pastikan Anda telah menginstal permata dan menjalankan bundle install.

gem 'jquery-rails'

gem 'turbolinks'

gem 'jquery-turbolinks'

Di application.js periksa apakah semuanya diperlukan seperti di bawah ini.

Waspadalah jika ini gotcha : ini //= require jquery.turbolinksdan tidak//= require jquery-turbolinks

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

Selanjutnya, tambahkan tautan yang sesuai di header application.html.erb.

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

Tampaknya ada banyak variasi tentang bagaimana menerapkan metode hapus yang saya asumsikan tergantung pada versi Rails yang Anda gunakan. Ini adalah deletesintaks yang saya gunakan.

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

Harapan yang membantu menggali seseorang keluar dari lubang yang sangat membuat frustrasi ini!

mikeym
sumber
0

Secara umum ketika Anda mendapatkan "Tidak ada rute yang cocok" tetapi Anda pikir Anda memiliki rute yang ditentukan kemudian periksa kembali kata kerja http / metode permintaan (apakah itu mendapatkan, menempatkan, memposting, menghapus dll) untuk rute itu .

Jika Anda menjalankan rute rake maka Anda akan melihat metode yang diharapkan dan Anda dapat membandingkan ini dengan log permintaan.

Muntasim
sumber