Rails7 Turbo流异常:渲染至yield而非指定turbo frame问题
Rails 7 Turbo 拉黑/解除拉黑功能异常修复方案
问题现象
点击Block按钮后,Turbo发送POST请求返回200,Unblock按钮正常显示;但点击Unblock按钮时,会重复发送Delete请求,且Turbo流将内容插入到布局的yield位置,而非指定的turbo frame中。
问题根源
- 保留了旧版UJS的
remote: true属性,导致Turbo与UJS同时处理请求,引发重复请求。 - 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
相关产品推荐
相关产品推荐

