Rails的link_to方法:在应该删除时却进行GET请求

60

我正在跟随Michael Hartl的Rails教程,但出现以下代码问题:

<%= link_to 'delete', user, :method => :delete, :confirm => "You sure?",
                                :title => "Delete #{user.name}" %>

发出一个GET请求(通过检查Rails服务器日志我已经验证过)。 我还验证了下面这行代码是否在我的应用视图中:

<%= javascript_include_tag :all %>

有一件事我不太明白,这也可能是我的问题所在: "delete" 方法在哪里定义的? 我在 Hartl 的源代码 中验证他在控制器中定义了一个 "destroy" 方法,而不是 "delete"。但是,即使我将 link_to 更改为 :method => :destroy,它仍然只发出 GET 请求。

我正在使用 Rails 3.1。有什么提示吗?

9个回答

80

请确保您的application.js文件中也有这个内容:

//= require jquery
//= require jquery_ujs 

显然我只有jquery没有jquery_ujs,直到我添加了它我才解决了同样的问题。

请注意,您可能需要在application.js内的任何导入语句之前添加这些行。


56

大多数浏览器实际上不支持DELETE动词,因此Rails通过修改它生成的HTML来模拟它。Rails添加了一个名为data-method的HTML5属性,并将其设置为"delete"。所以当用户点击链接时,它实际上被作为GET请求发出,但是data-method属性允许Rails魔法并且意味着您的路由代码应该将其识别为DELETE请求。

编辑:

您可以在控制台中进行测试。运行bundle exec rails c进入控制台,然后查看此生成的HTML:

helper.link_to "delete", "foobar/delete", :method => 'delete'

HTML应该是这样的:

<a href="foobar/delete" data-method="delete" rel="nofollow">delete</a>

4
谢谢,Jergason!这是Rails为我的“删除”生成的HTML代码--<a href="/users/1" data-confirm="You sure?" data-method="delete" rel="nofollow" title="Delete Jared Clement">delete</a>--看起来一切都没问题,但是当我点击该链接时,它不能删除。我正在使用Chrome浏览器,通常没有JavaScript的问题。你有任何想法在哪里可以寻找问题吗? - koggit
我的在这里: https://github.com/koggit/global2local-interpret/blob/master/config/routes.rbHartl的在这里: https://github.com/railstutorial/sample_app/blob/master/config/routes.rb相比之下看起来还不错,尽管我还不太理解路由。 - koggit
1
感谢您一直以来的帮助,Jergason。UserControler#destroy没有被触发。我可能找到了问题所在:Served asset /all.js - 404 Not Found。它试图获取 /assets/all.js,但该文件并不存在。我已经在谷歌上搜索了这个文件的相关信息,但是没有找到太多有用的结果。您能否提供一些关于此上下文中 all.js 的搜索词汇的建议? - koggit
2
谢谢——你的回复帮助我找到了关键词,从而找到了这篇文章的解决方案——https://dev59.com/lGw05IYBdhLWcg3wXQsh——不幸的是,尽管它有效,但**为什么**有效还不清楚。 哦,算了。 再次感谢! - koggit
以下的button_to解决方案对我来说是最好的方法! - JTE
显示剩余3条评论

22

你应该使用以下代码

<%= button_to "delete", @user_current, :method => "delete" %>

将这一行 //= require jquery_ujs 添加到application.js中即可解决问题。

 <%= link_to 'delete', user, :method => :delete, data: {:confirm => "You sure?" } ,
                            :title => "Delete #{user.name}" %>

7
如果您不想使用JQuery,将link_to替换为button_to可以解决这个问题,我相信。 - adarsh
1
我同意。如果你想使用link_to,就把jquery_ujs添加到application.js中。 - Hien Luong

6
由于浏览器不支持DELETE动词,Rails通过模拟一个标准的GETPOST请求来解决这个问题。 method: :delete工作方式是通过JavaScript处理所有带有data-method="delete"标记链接的方式修改请求,以便Rails将其处理为DELETE请求。这个JavaScript处理程序由jquery_ujs库提供。
可能出现以下几种问题:
  1. 确保在application.js中同时包含jqueryjquery_ujs。如果没有这两个,数据属性将无法被处理。
  2. 确保所涉及的链接确实指定了method: :delete选项。
  3. 确保您没有停止链接事件传播的某些原因,例如:
$( 'a' ).click( function( event ) {
    event.stopPropagation()
})

这将阻止执行 jquery_ujs 处理程序,请求将不会被修改,仍然保持标准的 GET 请求。


2
我在Michael的教程中遇到了同样的问题。 data-method="delete" 实际上按预期工作-它确实调用了控制器中的 destroy 动作。它尝试进行GET(并最终失败)的原因如下:
您会注意到,控制器中的一个 before_filter 设置为 signed_in_user,在 session_helper.rb 中,您会注意到 signed_in_user 调用 store_location(私有方法),该方法将更新 session[:return_to] 为当前 URL。
因此,在您的控制器的 destroy 动作中,它尝试 redirect_back_or,这将导致 GET current_url。 我修改了 signed_in_user 帮助程序,仅在用户尚未登录时调用 store_location

1

在Rails 5中:

我遇到了同样的问题,所有“DELETE”帖子都受到了影响,影响了我的crud页面和devise注销...为了解决这个问题,我只需要执行以下操作:

//= require rails-ujs


0

你想在Rails 6+中这样做:

 link_to(
  'Delete Me',
   some_controller_path(model),
   data: { method: :delete }
 )

0
使用button_to而不是link_to

0
我们所需要的就是添加下面这行代码。
//= require jquery_ujs 

看起来像是个bug:))


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接