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

Rails7 Turbo流异常:渲染至yield而非指定turbo frame问题

Rails 7 Turbo 拉黑/解除拉黑功能异常修复方案

问题现象

点击Block按钮后,Turbo发送POST请求返回200,Unblock按钮正常显示;但点击Unblock按钮时,会重复发送Delete请求,且Turbo流将内容插入到布局的yield位置,而非指定的turbo frame中。

问题根源

  1. 保留了旧版UJS的remote: true属性,导致Turbo与UJS同时处理请求,引发重复请求。
  2. Turbo Stream模板仅替换了按钮元素,未保留turbo_frame_tag结构,替换后目标frame不存在,Turbo只能将内容插入默认的yield位置。

修复步骤

1. 移除所有link_to中的remote: true属性

Rails 7默认启用Turbo,remote: true属于旧版UJS特性,会与Turbo冲突,需删除所有相关属性。

修改后的初始视图代码:

<%= turbo_frame_tag "block_unblock_button" do %>
  <% if @is_blocked_by_current_user %>
    <%= link_to unblock_profile_path(@user), data: { turbo_method: :delete, turbo_frame: "block_unblock_button" }, class: "btn btn-outline-primary mb-1 col-6 d-md-block mx-auto" do %>
      Unblock
    <% end %>
  <% else %>
    <%= link_to block_profile_path(@user), data: { turbo_method: :post, turbo_frame: "block_unblock_button" }, class: "btn btn-outline-primary mb-1 col-6 d-md-block mx-auto" do %>
      Block
    <% end %>
  <% end %>
<% end %>

2. 修改Turbo Stream模板,保留完整的turbo_frame_tag结构

替换操作需要维持目标frame的存在,否则后续请求找不到指定frame,会 fallback到布局的yield。

修改block.turbo_stream.erb:

<%= turbo_stream.replace "block_unblock_button" do %>
  <%= turbo_frame_tag "block_unblock_button" do %>
    <%= link_to unblock_profile_path(@user), data: { turbo_method: :delete, turbo_frame: "block_unblock_button" }, class: "btn btn-outline-primary mb-1 col-6 d-md-block mx-auto" do %>
      Unblock
    <% end %>
  <% end %>
<% end %>

修改unblock.turbo_stream.erb:

<%= turbo_stream.replace "block_unblock_button" do %>
  <%= turbo_frame_tag "block_unblock_button" do %>
    <%= link_to block_profile_path(@user), data: { turbo_method: :post, turbo_frame: "block_unblock_button" }, class: "btn btn-outline-primary mb-1 col-6 d-md-block mx-auto" do %>
      Block
    <% end %>
  <% end %>
<% end %>

3. 修复控制器unblock方法的安全问题

原代码中find_by可能返回nil,直接调用destroy会抛出异常,改用destroy_by更安全:

def unblock
  @user = User.find(params[:id])
  current_user.blocked_users.destroy_by(blocked_id: @user.id)
  @is_blocked_by_current_user = false

  respond_to do |format|
    format.turbo_stream
    format.html { redirect_to profile_path(params[:id]) }
  end
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 02:23:12