【问题标题】:Button_to in email not posting电子邮件中的 Button_to 未发布
【发布时间】:2014-08-07 18:41:52
【问题描述】:

查看更新以了解此问题的演变

在我的网站上,每个用户都有一个仪表板,她/他可以在其中单击链接以接受或拒绝请求。根据所单击的内容,请求记录随后会以相关状态进行修补。为了让用户更容易,我尝试将此仪表板嵌入到发给他们的电子邮件中,这样他们就不必直接访问网站;想一个看起来像这样的电子邮件:

你好,

您有以下请求,请点击请求旁边的接受/拒绝

  • 请求 A:接受、拒绝
  • 请求 B:接受、拒绝

....

到目前为止,实现这项工作的唯一方法是为电子邮件中使用的链接设置一组并行的 GET 路由,而不是为实际网站仪表板中使用的链接设置 PATCH 路由。

想知道是否有更好的方法吗?

路线

patch 'inventories/:id/accept', to: 'inventories#accept', as: 'lender_accept'
patch 'inventories/:id/decline', to: 'inventories#decline', as: 'lender_decline'
get 'inventories/:id/accept_email', to: 'inventories#accept', as: 'lender_accept_email'
get 'inventories/:id/decline_email', to: 'inventories#decline', as: 'lender_decline_email'

电子邮件中的链接

<%= "#{link_to 'ACCEPT', lender_accept_email_url(borrow), method: :patch} or #{link_to 'DECLINE', lender_decline_email_url(borrow)}" %>

网站仪表板上的链接

<%= "#{link_to 'ACCEPT', lender_accept_path(borrow), method: :patch} or #{link_to 'DECLINE', lender_decline_path(borrow), method: :patch}" %>

更新

好的,尝试使用button_to 生成一个 POST 表单以避免使用 GET 进行 POST,就像上面的“补丁”解决方案一样,仍然无法正常工作......

路线:

post 'inventories/:id/accept', to: 'inventories#accept', as: 'lender_accept'
post 'inventories/:id/decline', to: 'inventories#decline', as: 'lender_decline'

邮件视图:

<%="#{button_to 'YES', lender_accept_url(borrow), method: :post, id: "accept #{borrow.id}", style: "background-color:green; color: white; width: 40px; display: inline"} %>
<%="#{button_to 'NO', lender_decline_url(borrow), method: :post, id: "decline #{borrow.id}", style: "background-color:gray; width: 40px; display: inline"}" %>

我也在电子邮件上做了一个检查元素,只是为了确认button_to 正在生成适当的代码:

<form action="inventories/2037/decline" method="post" target="_blank" onsubmit="return window.confirm(&quot;You are submitting information to an external page.\nAre you sure?&quot;);"><div><input style="background-color:gray;width:40px;display:inline" type="submit" value="NO"></div></form>
  <div>
    <input style="background-color:gray;width:40px;display:inline" type="submit" value="NO">
  </div>
</form>

在我的邮件设置中,我将主机正确设置为我的域名,所以当我收到电子邮件并单击按钮时,我会适当地转到/inventories/2037/decline,但我仍然收到错误,因为显然日志说我还在尝试 GET ......这是为什么呢??

2014-08-17T06:18:03.206205+00:00 app[web.1]: ActionController::RoutingError (No route matches [GET] "/inventories/2037/decline"):

【问题讨论】:

  • 你能发布日志吗?顺便说一句,您可以使用 lender_accept_url(borrow) 而不是硬编码您的链接
  • 日志显示Started GET "/inventories/2008/accept",然后停止。好点,我更新到lender_accept_url
  • 如果您无法使用补丁,那么您可以更改您的网址以使用帖子,我相信它会起作用
  • 但问题是我不想创建任何新的东西,只是更新已经存在的记录的状态,顺便说一下刚刚编辑的问题以反映这种演变
  • 你可以使用post来更新你的记录

标签: ruby-on-rails email ruby-on-rails-4 parameter-passing link-to


【解决方案1】:

想知道是否有更好的方法吗?

发出GET 请求是理想的解决方案。不要使用任何其他请求。它要么不受电子邮件客户端支持,要么可能会增加很大的安全漏洞。

您认为大型网站使用post/patch 请求在电子邮件中执行此类操作是您的误解。它们都使用get 请求,它们包含一些令牌,当用户访问该网站时,这些令牌被绑定/触发该特定操作。

OK 尝试使用 button_to 生成 POST 表单以避免使用 GET 进行 POST,就像上面的“补丁”解决方案一样,仍然无法正常工作。

显然,它不会起作用。没有rails JavaScript 文件。此外,即使您包含它,它也不会工作,因为csrf-token 令牌。 Rails 应用程序默认不允许外部表单提交。

我的建议是使用一些额外的参数like www.example.com/dashboard?take_action=accept 将用户发送到您的dashboard,并使用JavaScript 来触发所需的操作。这将是最佳实践。这将避免您使用lender_accept 请求作为get

更准确地说,不要这样做

get 'inventories/:id/accept_email', to: 'inventories#accept', as: 'lender_accept_email'
get 'inventories/:id/decline_email', to: 'inventories#decline', as: 'lender_decline_email'

这很糟糕。因为,get 请求不适用于 updating/deleting

既然你想把这个actions链接到你的email,你应该把dashboard链接加上一些额外的参数。现在,只要您看到传递给电子邮件的参数,就可以使用 JavaScript 执行 accept/decline 操作。

更多:

【讨论】:

  • 好的,如果我理解正确,您建议保留我之前的 GET 解决方案。但是使用 Javascript 方式会更好一些吗?
  • 更新了答案。如果您有任何问题,请告诉我
  • 对不起,还是想澄清一下,因为在你的回答中你首先说:“发出 GET 请求是理想的解决方案”,但后来又说“不要这样做:”,什么是差异?另外,您是说没有一种纯粹的 Rails 方式可以做到这一点?
  • don't do this: &lt;the GET routes&gt; 我的意思是,您应该包括GET 请求。我没有说任何GET 要求的东西。不,这是纯粹的rails 方式。
  • 好的,我明白了,我做了更多的研究,所以现在我明白了为什么使用 GET 进行任何类型的 POST 都是不好的。但是,如果我使用 javascript 方式,它同样不安全吗?因为在 GET URL 中,我仍然有 ID 和操作,所以如果有人复制/粘贴该 URL,JS 操作将触发,它本质上是一样的,不是吗?抱歉,对这个很陌生
【解决方案2】:

我很确定电子邮件中的链接将无法使用“PATCH”方法,因为电子邮件没有rails.js。 (https://github.com/rails/jquery-ujs/blob/master/src/rails.js)

我不认为嵌入 rails.js 会起作用,因为大多数电子邮件合法提供商可能会在电子邮件中禁用 javascript。

您可以在路由中添加get 'inventories/:id/accept', to: 'inventories#accept', as: 'lender_accept' 来规避此问题,但如果您实际上要更改数据库中的任何内容,则使用get 是不好的做法。

我的简单解决方案是将用户链接到他们可以在您的网站上接受或拒绝的页面,而不是接受或拒绝电子邮件。

【讨论】:

  • 嗯,这是一个很好的临时解决方案,但大量网站允许您这样做...单击电子邮件中触发 POST 的链接,所以我必须相信某处有解决方案。如果我添加get 路由,会不会干扰patch
  • 我不能告诉你它是否会干扰,但我认为应该没问题。但是做测试。
  • 好吧,这行得通,我通过完全使用不同的名称来消除冲突。现在唯一的挑战是我是否可以避免 GET 并以某种方式使用 PATCH ......我改变了问题以反映这一点,但如果没有其他人想出更好的答案,我会接受这个作为答案
猜你喜欢
  • 2023-03-16
  • 1970-01-01
  • 2012-07-16
  • 1970-01-01
  • 1970-01-01
  • 2014-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多