没有路线匹配“ / users / sign_out”设计导轨3


386

我已经在应用程序上安装了devise,并在application.html.erb文件中应用了以下内容:

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

我跑步rake routes并确认所有路线均有效。

另外,在我的routes.rb文件中,我还有devise_for :usersroot :to => "home#index"

单击“注销”链接时,出现以下路由错误:

No route matches "/users/sign_out"

任何想法导致错误的原因是什么?


1
添加路线后,您是否重新启动了应用程序?路线更改仅在启动时生效。
Thilo-Alexander Ginkel,

2
是。只是为了安全起见再次这样做。另外,我在Stack上的其他地方读到,最新的devise gem与Rails 3.0.3不兼容可能是一个问题,因此我尝试将我的devise gem从1.4.2更改为gem 'devise', :git => 'git://github.com/plataformatec/devise.git'。那什么也没做。
2011年

不会更改Gemfile中的条目只是让您获得Devise的更新版本吗?您是否尝试指定了较低的版本号?
Leo Cassarani 2011年

你可以发布您的routes.rb文件
费利克斯

1
杰西的第二个答案如下。
2011年

Answers:


568

我认为登出路线是一种DELETE方法。这意味着您的登出链接需要如下所示:

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

您的不包括:method => :delete零件。另外,请注意,要执行此操作,还必须将其包含<%= javascript_include_tag :defaults %>在布局文件(application.html.erb)中。


3
可以肯定地说,我从未在任何Rails应用程序中都这样做。link_to "Sign out", destroy_user_session_path一直对我足够好。
Leo Cassarani 2011年

8
我做了测试,对我有用。别忘了事情会从一个版本更改为另一个版本(无论是在Rails还是Devise中)。此外,登出是状态变化的行为,不应使用GET方法来完成(以我的拙见)。
杰西·

23
有关更多信息,请在此处此处介绍为何在最新版本的Devise中对此进行了更改的理由。
杰西·德德克

6
我遇到了同样的问题,杰西的建议对我有用。我希望由于这种变化,任何正在运行设计轨道的人最终都会在这里结束...
johnnygoodman 2011年

2
您还可以在Web控制台中键入此内容以进行测试$("<a href='/users/sign_out' data-method='delete'>Sign out</a>").appendTo('body');-如果页面上已加载jQuery。
mraaroncruz 2012年

133

我在devise.rb中更改了这一行:

config.sign_out_via = :delete

config.sign_out_via = :get

它开始为我工作。


22
以前的方法是使用“ GET / users / sign_out”注销,但他们将其更改为“ DELETE”以使其更加RESTful。作者解释说,GET不应对服务器进行更改,例如注销。
乔纳森·阿拉德

2
这对我有用。尽管我认为这不是最佳实践,但其他答案却失败了。我不明白为什么!
轻微的绒毛

8
如果希望支持多种方法,也可以使用数组。例如:config.sign_out_via = [ :post, :delete ]devise_for :users, :sign_out_via => [ :post, :delete ],如devise / rails / routes.rb中所述
Hosam Aly 2012年

2
我不会使用GET请求退出,因为它使用户容易受到XSRF攻击。(黑客创建了一个带有src =“ foo.com/users/sign_out ” 图像标签的网站,用户访问该网站并注销了该网站)。
Ryan Doherty

1
@RyanDoherty ID我没记错,XSRF仍然可行(攻击者只需在目标URL上使用带有action =“ DELETE”的表格,然后在页面加载时自动提交即可)。
尼尔·尼森

60

您可能没有包含jquery_ujs javascript文件。确保您使用的是最新版本的jquery-ujs:https : //github.com/rails/jquery-ujs和可用的最新文件:

rails generate jquery:install

您应该没有更多的rails.js文件。如果这样做,您可能已经过时了。确保还在config / application.rb中将此文件加载了默认设置

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

(同样,你应该不会有rails.js文件在这里)。最后,添加Devise Wiki(haml风格)上记录的链接:

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

一切都会好起来的。


8
我的link_to中有:method =>'delete',问题不包括jquery_ujs,此解决方案解决了我的问题。请记住在您的gemfile中放置gem'jquery-rails'。
罗布·巴赞特

2
谢谢,这对我有用。除了使用默认值,您还可以使用javascript_include_tag "jquery_ujs"
Bnicholas 2012年

赶上了,谢谢!我正在使用require.js异步加载文件,却忘记了需要jquery_ujs。
Dan Fairaizl

我假设“ u”表示未压缩,并从中删除了这一行application.js。我想这是个错误的假设。谢谢。
杰夫(Jeff)

在将twitter引导程序从较少更改为sass之后,这个问题出现了(在我的第100个基于devise的应用程序中),我忘了将// = require jquery_ujs加回到我的application.js中。
2015年

31

能够使Logout链接成为DELETE RESTful调用的功能,需要data-method = "delete"使用rails代码使用html属性= link_to('Logout', destroy_user_session_path, :method => :delete)

但是,如果您没有jquery-ujs安装gem 或未通过调用application.html中的结果javascript = javascript_include_tag "application",则响应将作为GET请求发送,并且路由将失败。

如果您不想使用jquery-ujs或无法找到使其工作的方法,则有几种选择:

  1. 更改config.sign_out_via等于:getdevise.rb(不推荐,因为DELETE是适当的RESTful查询)
  2. 或将更link_to改为= button_to('Logout', destroy_user_session_path, :method => :delete)。使用button_toRails可以进行正确的DELETE调用。然后,您可以根据需要设置按钮的样式,使其看起来像一个链接。

从link_to更改为button_to对我有用,但我真的不明白为什么?除了html / css,究竟发生了什么变化?
Spyros Mandekis 2012年

1
它与rails'magic'有关,后者可以从button_to和link_to之类的函数自动生成html。碰巧的是,button_to的rails魔术指定了正确的RESTful DELETE调用,而link_to没有。如果我不得不猜测,那是因为html按钮元素可以处理DELETE调用(或捆绑有指定操作的隐藏字段),而常规链接则不能。
内森

谢谢你 我将我的应用设置为手动处理jquery,因此没有jquery-ujs。使用凉亭或捆扎机进行安装,并包括资产管道的相应行,即可解决此问题。
jrhorn424

1
在我看来,这是最安全,最便携的解决方案。

关于button_to,Rails form为整个操作生成一个。这就是为什么可以将:delete方法与button_to和不一起使用link_to,而仅查看生成的HTML的原因。
Fernando Fabreti 2015年

25

尝试添加一条新路线来设计/ sessions#destroy并链接到该路线。例如:

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

视图:

<%= link_to "Logout", logout_path %>

得到与mmichael相同的错误。上面的测试对我有用。
rtfminc 2011年

1
我也有与mmichael相同的错误。上面的解决方案可以工作,但不是固定的解决方案。Devise中的默认路由已经包括退出路由作为DELETE方法。通常,您不需要自己更改默认路由。这就是为什么您可以通过在link_to调用中简单地添加一个单独的参数来解决它的原因,如其他答案所述。
杰西·德德克

您不必在route.rb文件中添加路由,通过devise可以更改位于/ confit / initializers /目录中的devise.rb中的方法。
Travis Pessetto 2011年

6
永远都不会使用GET作为注销路径。
Jagira 2011年

@Jagira为什么?为什么不同时删除和获取?
hrdwdmrbl 2012年


13

我在rails 3.1.0上遇到了同样的问题,并且解决了在文件中添加以下几行:

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

如果使用凉亭,请尝试// ==需要jquery-ujs。
monteirobrena 2015年

10

除了一个例外,杰西的答案对我有用:

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

更改:

:delete

... 至:

'delete'

因此,对我有用的代码是:

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

感谢您发布此代码段,sign_out现在对我有用。
2012年

9

这个问题已经有很多答案。对我来说,问题有两个方面:

  1. 当我扩展路线时:

    devise_for :users do 
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  2. 我收到警告称此产品已贬值,因此我将其替换为:

    devise_scope :users do
       get '/users/sign_out' => 'devise/sessions#destroy'
    end
  3. 我以为我会删除我的jQuery。不好的选择。Devise使用jQuery来“伪造” DELETE请求并将其作为GET发送。因此,您需要:

    //= require jquery
    //= require jquery_ujs
  4. 并且当然与前面提到的链接相同:

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

您能解释第3点吗?我是它的受害者,我想进一步了解它
Rahul Dess

1
当然。您的网站实际上没有发送任何DELETE请求。坦率地说,它将仅使用GET和POST。因为在Rails社区中已经达成共识(出于充分的理由),我们想在提交DELETE请求时删除记录,所以我们需要使用一些技巧。在ERB中指定方法::delete rails会将其转换为HTML5标签:data-method =“ delete”并将其作为GET提交。现在,这是jQuery-ujs和jQuery的应用。它们允许应用程序识别出您正在执行的操作。这样您的请求可以与控制器动作匹配。
Lukasz Muzyka 2014年

没有那些宝石,这将行不通。当然,您可以更改devise的设置(在devise初始化程序中),并要求它使用GET而不是DELETE。
Lukasz Muzyka

7

加:

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

使用这些link_to标签

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

  or

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

在路线中添加:

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

7

另一种选择是将注销配置为GET而不是DELETE,您可以在以下行添加以下内容: /config/initializers/devise.rb

config.sign_out_via = :get

但是正如史蒂夫·克拉伯尼克(Steve Klabnik)在他的博客(http://blog.steveklabnik.com/2011/12/11/devise-actioncontroller-routingerror-no-route-matches-get-slash-users-slash-sign-out.html ),因为此方法的语义,请尝试使用DELETE。


只有这个答案为我工作设计3.5.1和4.2.3的Rails
萨加尔junnarkar

不要忘记重启服务器:)
杰克明

6

如果您使用的是Rails 3.1,请确保您的application.html.erb登出看起来像:

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

而且您的javascript包含行如下所示

<%= javascript_include_tag 'application' %>

我的猜测是,有些宝石会覆盖default.js位置的新结构。


谢谢!这让我发疯!
多里安(Dorian)2012年


5

好吧,对我来说,这只是删除:method =>:delete

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

5

这意味着在安装了jquery-rails gem之后,您还没有生成jquery文件。所以首先您需要生成它。

rails generate devise:install

第一种选择:

这意味着您必须更改以下行 /config/initializers/devise.rb

config.sign_out_via =:删除为config.sign_out_via =:get

第二种选择:

你只改变这一行<%= link_to "Sign out", destroy_user_session_path %><%= link_to "Sign out", destroy_user_session_path, :method => :delete %>的视图文件。

通常:method => :delete默认情况下不编写。


5

我想补充一点,即使它有点旧。

尽管具有:method =>:delete,“ sign_out”链接仍无法正常工作。

指出<%= javascript_include_tag :defaults %>必须包含的注释提醒我最近添加了JQuery Java脚本并使用了简单<script src=""/>标签来包含它们。

当我将它们从:defaults之后移到before时,sign_out重新开始工作。

希望这对某人有帮助。


5

大多数答案是不完整的。我已经多次遇到这个问题。需要解决两件事:

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

需要指定删除方法

然后devise使用jquery,因此您需要加载那些

   <%= javascript_include_tag "myDirectiveJSfile" %> 

并确保在myDirectiveJSfile.js中同时指定了jquery和jquery-ujs

//= require jquery
//= require jquery_ujs

5

不要忘记在application.js中添加以下行(Rails 3)

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

包含jquery_ujs在我的rails应用程序中,现在可以使用。


4

如果您将HTTPS与devise一起使用,则如果您的注销链接指向非安全版本,则会中断HTTPS。在后端,它重定向到安全版本。该重定向是一个GET,这会导致问题。

确保您的链接使用HTTPS。您可以protocol: "https"在url帮助器中强制使用它(确保您使用url帮助器而不是路径帮助器)。

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

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

3

问题始于rails 3.1 ... /app/assets/javascript/只是寻找application.js。

如果该文件不存在,请使用该名称创建一个文件,但我不知道为什么我的文件消失或从未创建过"rails new app"...

该文件是的实例jquery...


3

有很多解决方案。但主要用这个

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

或使用正确的sign_out方法配置devise.rb

在devise.rb中

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

3

路径的用法:get:delete方法:

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

注意:必须单独声明devise_for:users。请参阅dipole_moment的答案。
Taylored网站,

2

在您的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

并在您的application.html.erb中:

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

1
现在的语法为:devise_for:users,然后将获取内容放入devise_scope:user do注意:单数:user for devise_scope
Taylored网站

2

这就是我所做的(使用Rails 3.0和Devise 1.4.2):

  1. 确保您的页面加载rails.js
  2. 使用以下参数:'data-method'=>'delete'
  3. 添加此参数的好主意::rel =>'nofollow'

1

在“ devise_for:users”之前查看您的routes.rb是否具有“ resource:users”,然后尝试交换它们:

  1. 作品

    • devise_for:用户
    • 资源:用户
  2. 失败

    • 资源:用户
    • devise_for:用户

1

':method => :delete“页面是” data-method="delete"'让你的网页必须有jquery_ujs.js,将提交链接与方法删除不GET方法


1

我知道这是一个基于Rails 3的老问题,但是我只是在Rails 4.0.4上遇到并解决了这个问题。因此以为我会为所有在此版本中遇到此问题的人解决该问题。您的里程可能会有所不同,但这对我有用。

首先,请确保您已安装gems并运行bundle install。

gem 'jquery-rails'

gem 'turbolinks'

gem 'jquery-turbolinks'

在application.js中,检查是否需要所有内容,如下所示。

当心这个陷阱//= require jquery.turbolinks不是//= require jquery-turbolinks

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

接下来,在application.html.erb的标题中添加适当的链接。

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

关于实现delete方法的方法似乎有很多变化,我认为这取决于您使用的Rails的版本。这是delete我使用的语法。

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

希望能帮助人们从这个令人沮丧的洞中挖出来!


0

通常,当您获得“没有路由匹配”但您认为已定义了该路由时,请再次检查该路由的http谓词/请求方法(无论其get,put,post,delete等)

如果您运行耙式路由,那么您将看到预期的方法,并且可以将其与请求日志进行比较。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.