You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何指定method: :patch仍触发GET请求,出现No route matches错误?

问题描述

我想给未完成结账的客户发送含魔法链接的邮件,该链接可先登录用户,再触发控制器的update动作。邮件中使用的link_to代码如下:

<%= link_to(
           "Continue to checkout",
           "#{checkout_url(host: @account.complete_url, id: @user.current_subscription_cart)}?msgver=#{@user.create_message_verifier}",
           method: :patch,
           subscription_cart: { item_id: @item_id },
           ) %>

我的checkouts_controller包含update动作:

def update
  # update cart with item_id param and continue
end

路由配置为:

resources :checkouts, only: [:create, :update]

对应的update路由为:

checkout_path   PATCH   /checkouts/:id(.:format)    checkouts#update

生成的链接带有data-method="patch"属性:

<a data-method="patch" href="https://demo.test.io/checkouts/67?msgver=TOKEN">Continue to checkout</a>

=> https://demo.test.io/checkouts/67?msgver=TOKEN

但点击链接时却报错:

No route matches [GET] "/checkouts/67"

为何指定了method: :patch,仍发起GET请求?

原因与解决方案

核心原因

Rails的link_to指定method: :patch时,完全依赖Rails UJS(Unobtrusive JavaScript)脚本实现非GET请求的转换。但邮件客户端不会加载Rails的UJS脚本,点击链接时只会触发浏览器默认的GET请求,无法触发PATCH请求。

解决方法

方法1:改用GET请求处理逻辑

既然邮件环境无法支持UJS,可调整路由和控制器,允许通过GET请求执行原update动作的逻辑:

  • 修改路由,添加GET方法支持:
resources :checkouts, only: [:create]
# 同时支持PATCH和GET请求访问update动作
patch '/checkouts/:id', to: 'checkouts#update', as: :checkout
get '/checkouts/:id', to: 'checkouts#update', as: :checkout_continue
  • 更新link_to代码,去掉method: :patch参数,直接使用GET链接:
<%= link_to(
           "Continue to checkout",
           checkout_continue_url(
             host: @account.complete_url,
             id: @user.current_subscription_cart,
             msgver: @user.create_message_verifier,
             subscription_cart: { item_id: @item_id }
           )
           ) %>

注意:必须确保update动作通过msgver严格验证用户身份,防止恶意请求。

方法2:用表单模拟PATCH请求(邮件兼容方案)

在邮件中嵌入隐藏表单,用按钮模拟链接样式,通过表单提交发送PATCH请求(无需依赖JS):

<form action="<%= checkout_url(host: @account.complete_url, id: @user.current_subscription_cart) %>?msgver=<%= @user.create_message_verifier %>" method="post">
  <input type="hidden" name="_method" value="patch">
  <input type="hidden" name="subscription_cart[item_id]" value="<%= @item_id %>">
  <button type="submit" style="border: none; background: transparent; color: #0066cc; text-decoration: underline; cursor: pointer;">Continue to checkout</button>
</form>

大部分邮件客户端支持表单提交,这种方式能稳定触发PATCH请求。

内容的提问来源于stack exchange,提问作者pinkfloyd90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 13:35:13