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

如何结合turbo_confirm实现删除文章后的HTML页面跳转?

问题分析

Turbo 发起请求时,默认会将 text/vnd.turbo-stream.html 放在 Accept 请求头的最优先级位置,所以即便你在 URL 中指定了 format: :html,控制器依然会优先匹配 turbo_stream 格式的响应,导致无法触发 HTML 跳转。同时如果直接加 data-turbo="false" 会禁用 Turbo 的所有处理,包括 turbo_confirm 弹窗,所以需要兼顾两者需求。

解决方案

方案一:指定请求的 Accept 头为 HTML

通过给链接/表单添加 data-turbo-accept="text/html",让 Turbo 发送只接受 HTML 格式的请求,这样控制器就会走 format.html 分支,同时保留 turbo_confirm 的确认弹窗。

<%= link_to "Delete", admin_article_path(@article, redirect_to: admin_articles_path), 
      data: { turbo_method: :delete, turbo_confirm: "are you sure?", turbo_accept: "text/html" }, 
      class: "action-button" %>

优化后的 button_to 代码

button_to 会生成表单,只需给表单添加 turbo_accept 属性即可,同时无需重复设置 turbo_method(表单的 method: :delete 已足够):

<%= button_to "Delete Article", admin_article_path(@article, redirect_to: admin_articles_path), 
        method: :delete, 
        data: { turbo_confirm: "Are you sure?" }, 
        form: { data: { turbo_accept: "text/html" } }, 
        class: "secondary-button" %>

方案二:在控制器中根据场景强制响应 HTML

可以通过判断请求来源或自定义参数,让控制器在特定场景下直接返回 HTML 重定向:

def destroy
  article.destroy

  referer = params[:redirect_to] || request.referer || root_path

  # 从详情页删除或指定了 html_redirect 参数时,直接响应 HTML 跳转
  if params[:html_redirect] || request.referer&.include?(admin_article_path(@article))
    redirect_to referer, status: :see_other # 删除操作建议用 303 状态码而非 301
  else
    respond_to do |format|
      format.html { redirect_to referer, status: :see_other }
      format.turbo_stream { }
    end
  end
end

然后在详情页的删除链接中添加 html_redirect: true 参数:

<%= link_to "Delete", admin_article_path(@article, redirect_to: admin_articles_path, html_redirect: true), 
      data: { turbo_method: :delete, turbo_confirm: "are you sure?" }, 
      class: "action-button" %>

方案三:在 Turbo Stream 中实现跳转(推荐最佳实践)

无需修改视图,直接完善控制器的 turbo_stream 响应逻辑,让 Turbo 处理重定向,完全贴合 Turbo 的工作流:

def destroy
  article.destroy

  referer = params[:redirect_to] || request.referer || root_path

  respond_to do |format|
    format.html { redirect_to referer, status: :see_other }
    format.turbo_stream do
      # 判断是否从详情页发起删除请求,决定是跳转还是更新列表
      if request.referer == admin_article_path(@article)
        render turbo_stream: turbo_stream.redirect_to(referer)
      else
        # 列表页删除时,移除对应文章元素并更新计数(可根据需求调整)
        render turbo_stream: [
          turbo_stream.remove(@article),
          turbo_stream.update("articles_count", Article.count)
        ]
      end
    end
  end
end

这个方案既保留了 turbo_confirm 的弹窗,又能根据不同场景处理响应:列表页删除后更新 DOM,详情页删除后跳转回列表,无需额外修改视图代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:35:37