在 button_to 中使用 :method => delete 的目的是啥?

Posted

技术标签:

【中文标题】在 button_to 中使用 :method => delete 的目的是啥?【英文标题】:What is the purpose of using :method => delete in button_to?在 button_to 中使用 :method => delete 的目的是什么? 【发布时间】:2019-03-25 09:23:31 【问题描述】:

据我了解,html 不支持 HTTP 动词“DELETE”,因此在制作删除表单时需要使用不同的路由。

如果是这样,为什么这段代码可以正常工作,

<%=button_to 'Delete', :controller => :users, :action => 'destroy', :id => user.id, :method => :delete%>

但是,下面的代码不起作用

<%=button_to 'Delete', :controller => :users, :action => 'destroy', :id => user.id%>

它给出了错误: 'No route matches [POST] "users/1/"'

这个网址不应该是users/destroy/1吗?

【问题讨论】:

这是 HTTP 动词。 【参考方案1】:

旧版本的 HTML 仅支持 GETPOST。较新的版本包括PUTPATCHDELETE,它们被所有主要的网络浏览器视为XHR(XMLHttpRequest) 请求或简单的AJAX 请求。

当发出 PUT 或 PATCH 或 DELETE 请求时,Rails 在 javascript 的帮助下将这些请求作为 XHR 请求处理给客户端。当您的应用程序中的 Javascript 不工作或禁用时,这些请求将回退到 GET

现在回到不工作的代码 sn-p。你有以下

<%= button_to 'Delete', :controller => :users, :action => 'destroy', :id => user.id%>

button_to 默认创建一个 form 并将请求作为POST 发送,除非您明确覆盖它,就像在第一种情况下使用:method =&gt; :delete 所做的那样。所以上面的代码 sn-p 生成一个类似 users/1/ 的 url,但作为 POST 最终失败,因为你 没有在 routes.rb 中定义任何这样的路由

不应该解析为 users/destroy/1 的 url 吗?

不,当您在代码中使用 :method =&gt; :delete 时,生成的 url 将是 users/1 但请求以 DELETE 发送,最终会根据您的 有效请求routes.rb中定义的路由

【讨论】:

【参考方案2】:

输入 :method=>:delete 向 Rails 发出信号以创建具有隐藏值的表单,然后它将用于模拟表单的功能

method="delete"

如果有人能够解释为什么删除 :action =&gt; :destroy 会导致 :id =&gt; user.id 被视为 url 中的键和值(即 users?id=1 而不是 users/1 ),我将不胜感激。

【讨论】:

看起来它正在回退到 GET 方法 我相信这是因为在这种情况下,您明确设置了:id =&gt; user.id,它将自动参数化以使用 URL 发送。我认为您想要的是 &lt;%= button_to 'Destroy', user, method: :delete, data: confirm: 'Are you sure?' %&gt;.Rails 从 Active Record 变量 user 推断控制器类型(假设控制器与模型匹配)并且不需要设置 id 因为user 已经携带它。 【参考方案3】:

rails 约定在链接中提及方法(HTTP 动词),以便 Rails 知道要调用哪个控制器方法,因为没有 HTTP 动词 3 动作显示、更新和销毁,所有这 3 个动作都会生成相同的 url "/users/:id" 的路径(如果控制器是“UsersController”)。为了进一步阅读,我建议看看:

https://guides.rubyonrails.org/routing.html#crud-verbs-and-actions

编辑:

正如你在截图中看到的,如果你将 HTTP Verb 设置为 DELETE,Rails 会自动知道它必须运行 destroy 动作,否则 show、update 和 destroy 的路径是相同的。

【讨论】:

我的印象是 button_to 会默认发布,但即使不是这样,我也已经验证 :method=>:post 不起作用。我很好奇 Rails 在幕后做了什么来模拟一个带有 DELETE HTTP 动词的表单 我已经更新了我的答案,并通过我提到的链接,它一定会回答你的问题。 我不认为你完全明白我在问什么。我了解路由通过将 HTTP 动词与 url 配对来工作,并且我了解 rails 可以根据 HTTP 动词和 url 的组合推断要调用哪个控制器方法,但您不能将 method="delete" 与 html 表单一起使用。我在问 Rails 如何使用 :method=>:delete 哈希来模拟这种行为。【参考方案4】:

听起来您不需要代码答案,因为您已经有了一个工作版本。 Rails 在幕后做了很多事情,所以除非你去检查它,否则很难知道浏览器中到底发生了什么。

DELETE 可能无法用作 HTML &lt;form&gt; 标记中的属性,但它仍然是有效的 HTTP 请求。

Are the PUT, DELETE, HEAD, etc methods available in most web browsers?

What is the usefulness of PUT and DELETE HTTP request methods?

【讨论】:

我知道它们是有效的 HTTP 动词,虽然您是正确的,我有一个有效的代码解决方案,但使用我不理解的代码并不好。您是否熟悉有关 :method=>:delete 如何工作的任何文档?我找不到解决此问题的问题或围绕其行为的文档(url_for 和 button_to 的文档都没有太大帮助) 非常尊重您了解正在发生的一切的愿望。但是,如果您对 Rails 中的所有内容都这样做,您将花费大量时间来理解试图让您的生活“更轻松”的习语。我认为 Rails 的优点和缺点都是在幕后完成的。它非常适合原型制作,但难以定制。在某些时候,您必须要么使用它,要么使用不同的系统。要么这样,要么你最终会成为 Rails 的贡献者。 :)

以上是关于在 button_to 中使用 :method => delete 的目的是啥?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 button_to 不能使用方法: :put with slim in rails

无法使用link_to或button_to rails访问嵌套路由

Rails 5.1 button_to helper生成查询字符串而不是隐藏表单

Rails - 在控制器中路由动作的正确方法

向视图添加按钮

在 Rails 中将表格行变成链接