在 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 仅支持 GET
和 POST
。较新的版本包括PUT
、PATCH
和DELETE
,它们被所有主要的网络浏览器视为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 => :delete
所做的那样。所以上面的代码 sn-p 生成一个类似 users/1/
的 url,但作为 POST
最终失败,因为你 没有在 routes.rb
中定义任何这样的路由
不应该解析为 users/destroy/1 的 url 吗?
不,当您在代码中使用 :method => :delete
时,生成的 url 将是 users/1
但请求以 DELETE
发送,最终会根据您的 有效请求routes.rb
中定义的路由
【讨论】:
【参考方案2】:输入 :method=>:delete 向 Rails 发出信号以创建具有隐藏值的表单,然后它将用于模拟表单的功能
method="delete"
如果有人能够解释为什么删除 :action => :destroy
会导致 :id => user.id
被视为 url 中的键和值(即 users?id=1
而不是 users/1
),我将不胜感激。
【讨论】:
看起来它正在回退到 GET 方法 我相信这是因为在这种情况下,您明确设置了:id => user.id
,它将自动参数化以使用 URL 发送。我认为您想要的是 <%= button_to 'Destroy', user, method: :delete, data: confirm: 'Are you sure?' %>
.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 <form>
标记中的属性,但它仍然是有效的 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访问嵌套路由