Không có tuyến đường nào phù hợp với người dùng / người dùng / người đăng nhập.


386

Tôi đã cài đặt phát minh trên ứng dụng của mình và áp dụng những điều sau trong application.html.erbtệp của mình :

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

Tôi đã chạy rake routesvà xác nhận rằng tất cả các tuyến là hợp lệ.

Ngoài ra, trong routes.rbtập tin của tôi, tôi có devise_for :usersroot :to => "home#index".

Tôi gặp lỗi định tuyến sau khi nhấp vào liên kết "Đăng xuất":

No route matches "/users/sign_out"

Bất cứ ý tưởng những gì gây ra lỗi?


1
Bạn đã khởi động lại ứng dụng của mình sau khi thêm các tuyến đường? Thay đổi tuyến đường chỉ trở nên hiệu quả khi khởi động.
Thilo-Alexander Ginkel

2
Đúng. Chỉ cần làm lại để được an toàn. Ngoài ra, tôi đã đọc ở một nơi khác trên Stack rằng đó có thể là một vấn đề với viên ngọc phát minh mới nhất không tương thích với Rails 3.0.3 vì vậy tôi đã thử thay đổi viên ngọc phát minh của mình từ 1.4.2 sang gem 'devise', :git => 'git://github.com/plataformatec/devise.git'. Điều đó đã không làm gì mặc dù.
vich

Sẽ không thay đổi mục trong Gemfile chỉ giúp bạn có phiên bản Devise mới hơn bao giờ hết? Bạn đã thử chỉ định một số phiên bản thấp hơn?
Leo Cassarani

Bạn có thể đăng tập tin records.rb của bạn
felix

1
Câu trả lời thứ hai của Jessie dưới đây đã hoạt động hoàn hảo.
vich

Câu trả lời:


568

Tôi nghĩ rằng lộ trình đăng xuất là một DELETEphương pháp. Điều này có nghĩa là liên kết đăng xuất của bạn cần trông như thế này:

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

Của bạn không bao gồm :method => :deletemột phần. Ngoài ra, xin lưu ý rằng để làm việc này, bạn cũng phải đưa <%= javascript_include_tag :defaults %>vào tệp bố cục ( application.html.erb).


3
Tôi có thể nói rằng tôi chưa bao giờ phải làm điều đó trong bất kỳ ứng dụng Rails nào. link_to "Sign out", destroy_user_session_pathluôn luôn đủ tốt cho tôi
Leo Cassarani

8
Tôi đã làm bài kiểm tra và nó làm việc cho tôi. Đừng quên rằng mọi thứ thay đổi từ phiên bản này sang phiên bản khác (có thể là Rails hoặc Devise). Ngoài ra, đăng xuất là hành vi thay đổi trạng thái không nên được thực hiện bằng phương thức GET (theo ý kiến ​​khiêm tốn của tôi).
Jessie Dedecker

23
Để biết thêm thông tin, lý do tại sao điều này đã được thay đổi trong phiên bản mới nhất của Devise được mô tả ở đâyđây .
Jessie Dedecker

6
Tôi gặp vấn đề tương tự và đề nghị của Jane làm việc cho tôi. Tôi hy vọng bất cứ ai đang chạy qua railscast cuối cùng sẽ kết thúc ở đây do sự thay đổi này ...
johnnygoodman

2
bạn cũng có thể nhập cái này vào bảng điều khiển web để kiểm tra $("<a href='/users/sign_out' data-method='delete'>Sign out</a>").appendTo('body');- nếu jQuery được tải trên trang.
mraaroncruz

133

Tôi đã thay đổi dòng này trong devise.rb:

config.sign_out_via = :delete

đến

config.sign_out_via = :get

và nó bắt đầu làm việc cho tôi.


22
Cách nó đã được thực hiện trước đó là đăng xuất bằng cách sử dụng "NHẬN / người dùng / dấu hiệu", nhưng họ đã thay đổi nó thành "XÓA" để làm cho nó trở nên RESTful hơn. Tác giả giải thích rằng GET không nên thay đổi máy chủ như đăng xuất.
Jonathan Allard

2
Điều này làm việc cho tôi. Trong khi tôi đánh giá cao nó không phải là một thực tiễn tốt nhất, các câu trả lời khác đã thất bại. Tôi không thể hiểu tại sao !!
Fuzz nhẹ

8
Cũng có thể sử dụng một mảng nếu bạn muốn hỗ trợ nhiều phương thức. Ví dụ: config.sign_out_via = [ :post, :delete ]hoặc devise_for :users, :sign_out_via => [ :post, :delete ], như được mô tả trong devise / rails / tuyến.rb .
Hosam Aly

2
Tôi sẽ không sử dụng yêu cầu GET để đăng xuất vì nó mở ra cho người dùng một cuộc tấn công XSRF. (Hacker tạo một trang web có thẻ hình ảnh với src = " foo.com/users/sign thừng ", người dùng truy cập vào trang web và đăng xuất).
Ryan Doherty

1
@RyanDoherty Id Tôi không nhầm, XSRF vẫn có thể (kẻ tấn công chỉ cần sử dụng một biểu mẫu với hành động = "XÓA" trên url đích, sau đó tự động gửi nó khi tải trang).
Maël Nison

60

Bạn có thể không bao gồm tệp javascript jquery_ujs. Đảm bảo bạn đang sử dụng phiên bản mới nhất của jquery-ujs: https://github.com/rails/jquery-ujs và các tệp cuối cùng có sẵn:

rails generate jquery:install

Bạn không nên có thêm tệp rails.js. Nếu bạn làm như vậy, có lẽ bạn đã lỗi thời. Đảm bảo rằng tệp này cũng được tải với mặc định, trong config / application.rb

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

(Một lần nữa, bạn không nên có tệp rails.js ở đây). Cuối cùng, thêm liên kết như tài liệu trên Devise wiki (kiểu haml):

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

Và mọi thứ sẽ ổn thôi.


8
Tôi đã có: phương thức => 'xóa' trong link_to của tôi, vấn đề là jquery_ujs không được bao gồm, giải pháp này đã giải quyết vấn đề của tôi. Hãy nhớ đặt gem 'jquery-rails' trong gemfile của bạn.
Rob Bazinet

2
Cảm ơn điều này đã làm việc cho tôi. Thay vì sử dụng mặc định, bạn cũng có thể sử dụngjavascript_include_tag "jquery_ujs"
Bnicholas

Bắt tốt, cảm ơn bạn! Tôi đang sử dụng các tệp.j.j để tải các tệp không đồng bộ và quên yêu cầu jquery_ujs.
Dan Fairaizl

Tôi giả sử "u" có nghĩa là không nén và loại bỏ dòng này khỏi application.js. Giả định xấu, tôi cho rằng. Cảm ơn.
Jeff

Vấn đề này đã được xử lý (trong ứng dụng dựa trên phát minh thứ 100 của tôi) sau khi thay đổi bootstrap twitter từ ít thành sass và tôi đã quên thêm lại // = yêu cầu jquery_ujs vào application.js của tôi.
Joe

31

Khả năng làm cho liên kết Đăng xuất thành một cuộc gọi XÓA RESTful yêu cầu một thuộc tính html data-method = "delete"bằng cách sử dụng mã rails = link_to('Logout', destroy_user_session_path, :method => :delete).

Tuy nhiên, nếu bạn chưa jquery-ujscài đặt gem hoặc không gọi javascript kết quả trong application.html thông qua= javascript_include_tag "application" , phản hồi sẽ được gửi dưới dạng yêu cầu GET và tuyến sẽ thất bại.

Bạn có một vài lựa chọn nếu bạn không muốn sử dụng jquery-ujshoặc không thể tìm ra cách để nó hoạt động:

  1. Thay đổi config.sign_out_viathành bằng :gettrong devise.rb(không được đề xuất, vì XÓA là truy vấn RESTful thích hợp)
  2. HOẶC Thay đổi link_tothành = button_to('Logout', destroy_user_session_path, :method => :delete). Với button_toRails sẽ thực hiện các công việc nặng nề khi thực hiện cuộc gọi XÓA thích hợp. Sau đó, bạn có thể tạo kiểu cho nút trông giống như một liên kết nếu bạn muốn.

Thay đổi từ link_to sang button_to làm việc cho tôi, nhưng tôi thực sự không hiểu tại sao? Chính xác thì điều gì đã thay đổi ngoài html / css?
Spyros Mandekis

1
Nó phải thực hiện với 'ma thuật' đường ray tự động tạo html từ các chức năng như button_to và link_to. Nó chỉ xảy ra rằng ma thuật đường ray cho button_to chỉ định cuộc gọi RESTful DELETE thích hợp và link_to thì không. Nếu tôi phải đoán, tôi sẽ nói lý do là các phần tử nút html có thể xử lý một cuộc gọi XÓA (hoặc gói với một trường ẩn chỉ định hành động) trong khi các liên kết thông thường không thể.
Will Nathan

Cám ơn vì cái này. Tôi thiết lập ứng dụng của mình để xử lý thủ công jquery, vì vậy tôi không có jquery-ujs. Cài đặt với bower hoặc bundler và bao gồm dòng thích hợp cho đường ống tài sản sẽ khắc phục vấn đề.
jrhorn424

1
Đây dường như là giải pháp an toàn và di động nhất.

Giới thiệu button_to, Rails tạo ra formcho toàn bộ hành động. Đó là lý do tại sao có thể sử dụng :deletephương thức mà button_tokhông phải với link_to, chỉ cần xem HTML được tạo.
Fernando Fabreti

25

Hãy thử thêm một tuyến đường mới để tạo ra / phiên # hủy và liên kết đến đó. Ví dụ:

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

lượt xem:

<%= link_to "Logout", logout_path %>

Bắt lỗi tương tự như mmichael. Bài kiểm tra trên có tác dụng với tôi.
rtfminc

1
Tôi cũng có lỗi tương tự như mmichael. Giải pháp trên sẽ có hiệu quả nhưng không phải là cách khắc phục. Các tuyến mặc định trong Devise đã bao gồm tuyến đăng xuất dưới dạng phương thức XÓA. Thông thường bạn không cần phải thay đổi các tuyến mặc định. Đó là lý do tại sao bạn có thể khắc phục bằng cách thêm một tham số riêng vào link_tocuộc gọi, như được mô tả trong câu trả lời khác.
Jessie Dedecker

Bạn không phải thêm một tuyến đường vào tuyến đường.rb, devise cho phép bạn thay đổi phương thức trong devise.rb trong thư mục / confit / khởi tạo /.
Travis Pessetto

6
Không bao giờ có đường dẫn đăng xuất là NHẬN.
Jagira

@Jagira tại sao? Tại sao không cả XÓA và NHẬN?
hrdwdmrbl

14

Sử dụng nó trong tập tin records.rb của bạn:

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

13

Tôi gặp vấn đề tương tự với rails 3.1.0 và tôi đã giải quyết thêm vào tệp các dòng sau:

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

Nếu sử dụng Bower, hãy thử // = yêu cầu jquery-ujs.
monteirobrena

10

Với một ngoại lệ, câu trả lời của Jane làm việc cho tôi:

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

thay đổi:

:delete

... đến:

'delete'

Vì vậy, mã làm việc cho tôi là:

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

Cảm ơn bạn đã đăng đoạn mã này, SignFor hoạt động cho tôi ngay bây giờ.
buk

9

Nhiều câu trả lời cho câu hỏi rồi. Đối với tôi, vấn đề là hai lần:

  1. khi tôi mở rộng các tuyến đường của mình:

    devise_for :users do 
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  2. Tôi đã nhận được cảnh báo rằng điều này bị khấu hao vì vậy tôi đã thay thế nó bằng:

    devise_scope :users do
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  3. Tôi nghĩ rằng tôi sẽ loại bỏ jQuery của tôi. Lựa chọn tồi. Devise đang sử dụng jQuery để "giả mạo" yêu cầu XÓA và gửi nó dưới dạng GET. Do đó, bạn cần phải:

    //= require jquery
    //= require jquery_ujs
  4. và tất nhiên cùng một liên kết như nhiều người đã đề cập trước đây:

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

bạn có thể giải thích điểm thứ 3..tôi là nạn nhân của nó và tôi muốn hiểu nó nhiều hơn
Rahul Dess

1
Chắc chắn rồi. Trang web của bạn không thực sự gửi bất kỳ yêu cầu XÓA. Thẳng thắn mà nói nó sẽ chỉ sử dụng GET và POST. Bởi vì trong cộng đồng Rails, chúng tôi đã đồng ý rằng (vì lý do chính đáng), chúng tôi muốn xóa các bản ghi khi gửi yêu cầu XÓA, chúng tôi cần sử dụng một mẹo nhỏ. Khi trong ERB của bạn, bạn chỉ định phương thức :: xóa đường ray sẽ chuyển đổi thẻ đó thành thẻ HTML5: data-method = "xóa" và gửi nó dưới dạng GET. Bây giờ, đây là nơi jQuery-ujs và jQuery khởi động. Họ cho phép ứng dụng nhận ra đây là những gì bạn đang làm. Vì vậy, yêu cầu của bạn có thể được khớp với hành động của bộ điều khiển.
Lukasz Muzyka

không có những viên đá quý này, nó sẽ không hoạt động. Tất nhiên, bạn có thể thay đổi cài đặt của devise (trong trình khởi tạo devise) và yêu cầu nó sử dụng GET thay vì XÓA.
Lukasz Muzyka

7

Thêm vào:

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

Sử dụng các thẻ link_to này

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

  or

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

Trong các tuyến đường thêm:

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

7

Tùy chọn khác là định cấu hình đăng xuất thành GET thay vì XÓA, bạn có thể thực hiện thêm dòng sau vào /config/initializers/devise.rb

config.sign_out_via = :get

Nhưng như Steve Klabnik đã viết trên blog của mình (http://blog.steveklabnik.com/2011/12/11/devise-actioncontroll-routingerror-no-route-matches-get-slash-users-slash-sign-out.html ) cố gắng sử dụng XÓA vì ngữ nghĩa của phương thức này.


Chỉ có câu trả lời này làm việc cho tôi cho Devise 3.5.1 & Rails 4.2.3
sagar Junnarkar

Đừng quên khởi động lại máy chủ :)
jackmin

6

Nếu bạn đang sử dụng Rails 3.1, hãy đảm bảo ứng dụng của bạn.html.erb đăng xuất trông giống như:

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

Và rằng javascript của bạn bao gồm dòng trông như sau

<%= javascript_include_tag 'application' %>

Tôi đoán là một số đá quý ghi đè lên cấu trúc mới của vị trí default.js.


Cảm ơn! Điều này đã khiến tôi phát điên!
Dorian

5

Kiểm tra nó với mã nguồn trong github:

https://github.com/plataformatec/devise/commit/adb127bb3e3b334cba903db2c21710e8c41c2b40#lib/generators/temsheet/devise.rb (ngày: 27 tháng 6 năm 2011)

  • # Phương thức HTTP mặc định được sử dụng để đăng xuất tài nguyên. Mặc định là: có được. 188
  • # config.sign thừng_via =: nhận 187
  • # Phương thức HTTP mặc định được sử dụng để đăng xuất tài nguyên. Mặc định là: xóa. 188
  • config.sign thừng_via =: xóa

5

Chà, đối với tôi, nó chỉ xóa: phương thức =>: xóa

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

5

Điều này có nghĩa là bạn chưa tạo các tệp jquery sau khi bạn đã cài đặt đá quý jquery-rails. Vì vậy, trước tiên bạn cần phải tạo ra nó.

rails generate devise:install

Lựa chọn đầu tiên:

Điều này có nghĩa là bạn phải thay đổi dòng sau /config/initializers/devise.rb

config.sign thừng_via =: xóa vào config.sign thừng_via =: get

Sự lựa chọn thứ hai:

Bạn chỉ thay đổi dòng này <%= link_to "Sign out", destroy_user_session_path %>thành <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>trên tập tin xem.

Thường :method => :deletekhông được viết theo mặc định.


5

Tôi muốn thêm vào điều này mặc dù nó hơi cũ.

liên kết "SignDef" không hoạt động, mặc dù có: phương thức =>: xóa.

Nhận xét chỉ ra rằng <%= javascript_include_tag :defaults %>phải được đưa vào nhắc nhở tôi rằng gần đây tôi đã thêm tập lệnh java JQuery và sử dụng đơn giản<script src=""/> các thẻ để đưa chúng vào.

Khi tôi chuyển chúng từ sau: mặc định sang trước, dấu hiệu bắt đầu hoạt động trở lại.

Hy vọng điều này sẽ giúp được ai đó.


5

Hầu hết các câu trả lời là một phần. Tôi đã nhấn vấn đề này nhiều lần. Hai điều cần được giải quyết:

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

phương pháp xóa cần được chỉ định

Sau đó, devise sử dụng jquery, vì vậy bạn cần tải chúng

   <%= javascript_include_tag "myDirectiveJSfile" %> 

và đảm bảo rằng CẢ HAI jquery và jquery-ujs được chỉ định trong myDirectiveJSfile.js của bạn

//= require jquery
//= require jquery_ujs

5

Đừng quên bao gồm dòng sau trong application.js của bạn (Rails 3)

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

Bao gồm jquery_ujsvào ứng dụng rails của tôi và nó hoạt động ngay bây giờ.


4

Nếu bạn đang sử dụng HTTPS , nó sẽ bị hỏng nếu liên kết đăng xuất của bạn là phiên bản không bảo mật. Ở mặt sau, nó chuyển hướng đến phiên bản an toàn. Chuyển hướng đó là một GET, gây ra vấn đề.

Đảm bảo liên kết của bạn sử dụng HTTPS. Bạn có thể buộc nó protocol: "https"trong trình trợ giúp url của bạn (đảm bảo bạn sử dụng trình trợ giúp url chứ không phải trình trợ giúp đường dẫn).

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


3

Vấn đề bắt đầu với rails 3.1 ... /app/assets/javascript/chỉ cần tìm application.js.

Nếu tệp không tồn tại, hãy tạo một tệp có tên đó, tôi không biết tại sao tệp của mình biến mất hoặc không bao giờ được tạo "rails new app"....

Tập tin đó là ví dụ cho jquery....


3

Có rất nhiều giải pháp. nhưng chủ yếu sử dụng cái này,

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

hoặc cấu hình devise.rb với phương thức đăng nhập thích hợp

Trong devise.rb

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

3

sử dụng :get:deletephương pháp cho đường dẫn của bạn:

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

Lưu ý: phải có devise_for: người dùng khai báo riêng biệt với điều này. xem câu trả lời từ dipole_moment.
Trang web Taylored

2

Trong tuyến đường của bạn.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

và trong ứng dụng của bạn.html.erb:

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

1
Cú pháp bây giờ là: devise_for: người dùng sau đó phải được đặt trong devise_scope: user do NOTE: singular: user for devise_scope
Các trang web Taylored

2

Đây là những gì tôi đã làm (với Rails 3.0 và Devise 1.4.2):

  1. Đảm bảo trang của bạn tải rails.js
  2. Sử dụng thông số này: 'phương thức dữ liệu' => 'xóa'
  3. Ý tưởng hay để thêm thông số này :: rel => 'nofollow'

1

Xem các tuyến đường của bạn có "tài nguyên: người dùng" trước "devise_for: users" không, sau đó thử hoán đổi chúng:

  1. Làm

    • devise_for: người dùng
    • tài nguyên: người dùng
  2. Thất bại

    • tài nguyên: người dùng
    • devise_for: người dùng

1

các ':method => :delete'trong trang là' data-method="delete"'để trang của bạn phải có jquery_ujs.js, nó sẽ gửi liên kết với phương pháp xóa không method get


1

Tôi biết đây là một câu hỏi cũ dựa trên Rails 3 nhưng tôi chỉ chạy vào và giải nó trên Rails 4.0.4. Vì vậy, tôi nghĩ rằng tôi đã khắc phục nó cho bất kỳ ai gặp phải vấn đề này với phiên bản này. Số dặm của bạn có thể thay đổi nhưng đây là những gì làm việc cho tôi.

Trước tiên hãy chắc chắn rằng bạn đã cài đặt đá quý và chạy cài đặt gói.

gem 'jquery-rails'

gem 'turbolinks'

gem 'jquery-turbolinks'

Trong application.js kiểm tra xem mọi thứ được yêu cầu như dưới đây.

Cẩn thận nếu điều này có Gotcha : nó //= require jquery.turbolinksvà không//= require jquery-turbolinks

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

Tiếp theo, thêm các liên kết thích hợp trong tiêu đề của application.html.erb.

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

Dường như có nhiều biến thể về cách thực hiện phương thức xóa mà tôi giả sử phụ thuộc vào phiên bản Rails bạn đang sử dụng. Đây là deletecú pháp tôi đã sử dụng.

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

Hy vọng rằng sẽ giúp đào ai đó ra khỏi cái lỗ rất bực bội này!


0

Nói chung khi bạn nhận được "Không có tuyến trùng khớp" nhưng bạn nghĩ rằng bạn đã xác định tuyến đường đó, sau đó kiểm tra kỹ phương thức http / request request (cho dù đó là get, put, post, xóa, v.v.) cho tuyến đường đó .

Nếu bạn chạy các tuyến cào thì bạn sẽ thấy phương thức dự kiến ​​và bạn có thể so sánh điều này với nhật ký yêu cầu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.