设计:为什么我的注销链接不起作用?

时间:2011-08-04 18:11:41

标签: ruby-on-rails devise

问题:简而言之,当我尝试在我的应用程序中安装注销链接时,它无法正常工作。这里有我认为可以放在这里的背景(如果你还需要其他东西,请戳我)......

我在haml视图中得到了这个:

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

它在视图中生成:

<a href="/users/sign_out" data-method="delete" rel="nofollow">Logout</a>

我验证了在我的config / initializers / devise.rb中我将此设置取消注释并更正:

config.sign_out_via = :delete

我验证了以下路线:

destroy_user_session DELETE /users/sign_out(.:format) {:action=>"destroy", :controller=>"devise/sessions"}

我的routes.rb中也有这点诡计,我怀疑这与我的问题有关:

devise_for :users, :controllers => {:sessions => "devise/sessions", :registrations => "users"}
resources :users

最后一点是因为我想在自己的控制器中管理(编辑,创建和删除)用户。

我收到的错误消息如下:

ActiveRecord::RecordNotFound in UsersController#show

Couldn't find User with ID=sign_out
Rails.root: /home/jaydel/projects/mbsquared-projects/Wilson-Goldrick

app/controllers/users_controller.rb:16:in `show'

在我的服务器日志中,我看到了这个请求:

Started GET "/users/sign_out" for 127.0.0.1 at 2011-08-04 13:08:51 -0500
  Processing by UsersController#show as HTML
  Parameters: {"id"=>"sign_out"}

有人有什么想法吗?

17 个答案:

答案 0 :(得分:83)

解决此问题的正确方法(REST方式)是更改注销链接以使用DELETE方法。这是一个非常简单的修复,改变了这个:

link_to "Log out", destroy_user_session_path

到此:

link_to "Log out", destroy_user_session_path, :method => :delete 

答案 1 :(得分:33)

当我从application.js这一行删除时,我遇到了与rails 3.2相同的问题:

//= require jquery_ujs

所以,我认为你必须在application.js中插入这一行,如果你还没有。

PS。此行为意味着jquery的rails适配器不起作用。因此,您应确保它是否已在浏览器中的html中加载。您应该在开发模式下测试它,因为您将在生产中使用压缩的js,并且很难在那里找到它。

答案 2 :(得分:16)

问题在于,在您的日志中,注销请求是GET请求。

Started GET "/users/sign_out"

但是注销路线是DELETE

destroy_user_session DELETE /users/sign_out(.:format) 

你得到异常的原因是它与resources :users创建的其中一条路线相混淆,就像

edit_user GET /users/(:id)(.:format) {:action=>"edit", :controller=>"users"}

基本上'sign_out'被误认为是id。

我不确定为什么删除链接不会作为DELETE请求进行。虽然改变了

config.sign_out_via = :delete

成为:get可能会解决问题。

答案 3 :(得分:6)

你需要两个 //= require jquery //= require jquery_ujs

&安培;&安培;这些包含在application.js

gem 'jquery-rails'

。显然,如果由于某种原因它不存在,请不要忘记将其添加到Gemfile。

parameters

答案 4 :(得分:4)

这是一个老问题,但接受的答案并不是解决这个问题的正确方法(尽管这是对问题的良好诊断)。

今天遇到这个时,我的路线文件显示为:

  root :to => 'welcome#index' 

  resources :users    
  devise_for :users

正如Olives所提到的,资源声明只会导致/ users / anything绊倒。我只需要改变路线的顺序......

 root :to => 'welcome#index' 

  devise_for :users
  resources :users

答案 5 :(得分:4)

为了使用DELETE执行请求,需要jQuery。确保你没有从application.js中删除它。

答案 6 :(得分:2)

我已经检查了所有这些解决方案,但没有人为我工作过。最后我发现在标题中我删除了两行,包括应用程序标签和csrf meta

所以,如果有人此问题没有解决问题 - 检查你是否有页面标题(HAML表示法)

= javascript_include_tag 'application'
= csrf_meta_tags 

答案 7 :(得分:2)

这是一个老问题,但我想要一种不需要JavaScript的方法。 Rails支持&#34; DELETE&#34;类似于具有将method设置为delete的隐藏输入的请求。使用真实的<form>,让Rails生成必要的隐藏输入:

<%= form_for(resource, as: resource_name,
    url: destroy_user_session_path, html: { method: :delete }) do |f| %>
  <%= f.submit "Log out" %>
<% end %>

以上产生的内容如下:

<form accept-charset="UTF-8" action="/users/sign_out" method="post">
  <div style="display:none">
    <input name="utf8" type="hidden" value="✓">
    <input name="_method" type="hidden" value="delete">
    <input name="authenticity_token" type="hidden" value="1234">
  </div>
  <input name="commit" type="submit" value="Log out">
</form>

答案 8 :(得分:1)

您还必须检查resources :usersdevise_for :users是否为链接方法删除

link_to "Logout", destroy_user_session_path, method: :delete

如果两者都正确,则您的注销按钮应该可以正常工作

答案 9 :(得分:1)

如果你的rails应用程序中还有多个jquery源,你需要使用Gemfile中指定的默认值

在你的Gemfile中确保你有这个

gem 'jquery-rails'

并且在您的资产中,您没有任何其他JQuery源文件。

在我的情况下,我有一个第二个JQuery文件,而不是Gemfile中声明的默认文件,因此它引起了冲突。

如果您以前拥有这些来源,请务必再次预编译资产(如果您之前已经这样做了)

答案 10 :(得分:1)

我必须以不同的方式解决这个问题,因为我的application.rb有:

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

并且仍然失败。事实证明我需要在/ environment / development,test和production.rb中设置config.serve_static_assets = trueThis link帮助我解决了这个问题。

答案 11 :(得分:1)

由于OP提到了设计并且这个问题也发生在我身上,我只想插话。@ Ross Allen在你不想使用jQuery_ujs时得到了正确的答案。 Rails提供了几个帮助器来解决这个问题,而没有jQuery。

这是Ross的答案,但是使用了Devise的current_user模型:

<%= form_for(current_user,
    url: destroy_user_session_path, html: { method: :delete }) do |f| %>
    <%= f.submit "Log out" %>
<% end %>

或者创建类似形式的更简洁的button_to助手:

<%= button_to "Log out", destroy_user_session_path, method: :delete %>

答案 12 :(得分:0)

我同意使用http DELETE方法更加安静,我喜欢创建一个简单的端点来使用GET方法销毁用户会话。

将其添加到config / routes.rb

devise_scope :user do
  get '/logout',  :to => 'sessions#destroy'
end

答案 13 :(得分:0)

如果您在生产中发现此问题并且您正在使用资产管道,则通常需要:

rake assets:clobber以清除您的公共资产。然后在提交和推送代码之前rake assets:precompile(除非你的推送也预编译,也就是Heroku)。

答案 14 :(得分:0)

原因可能是错误的订单连接bootstrap-sprockets

正确的顺序:

// app/assets/javascripts/application.js

...

//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap-sprockets
//= require_tree .

答案 15 :(得分:0)

如上面Tombart所述,我的答案是在我的application.js文件中放回rails-ujs调用。

//= require rails-ujs
//= require turbolinks

我最初删除了它们以阻止错误重新评估页脚中的脚本。我的解决方法是使用页脚中我想要的资源创建一个footer.js编译文件。

//= require jquery-3.2.1.min
//= require jquery-ui-1.12.1.min
//= require materialize
//= require init

然后在我的/initializers/assets.rb文件中添加预编译

Rails.application.config.assets.precompile += %w( footer.js )

然后,您可以在layout / application.html.erb文件中调用以下内容。

<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'footer' %>

我将应用程序行保留在标题中,并添加了我的新&#34;页脚&#34;在我的身体标签结束前打电话。

答案 16 :(得分:0)

1)我觉得你可能需要安装在gem下面,请求方法:: delete会工作,否则它可能会得到

https://github.com/rails/jquery-rails

2)在application.js

中添加以下两行
//= require jquery
//= require jquery_ujs