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

Rails中Turbo Stream响应异常为HTML的问题修复咨询

问题描述

我在profile/follow_button页面设置了如下turbo_frame_tag:

<%= turbo_frame_tag "#{dom_id(@user)} follow_user" do %>
  <% if following?(user) %>
    <%= link_to "Unfollow", profile_unfollow_path(id: user.id), method: :delete, class: "" %>
  <% else %>
    <%= link_to "Follow", profile_follow_path(id: user.id), method: :post, class: "" %>
  <% end %>
<% end %>

为通过Hotwire实现点击加载关注/取消关注动作,我在控制器编写了如下代码:

def follow
    Relationship.create_or_find_by(follower_id: current_user.id, followee_id: @user.id)
    # redirect_back(fallback_location: root_path)
    respond_to do |format|
      format.turbo_stream do
        render turbo_stream: update_action_follow
      end
    end
  end


  def unfollow
    current_user.followed_user.where(follower_id: current_user.id, followee_id: @user.id).destroy_all
    # redirect_back(fallback_location: root_path)
    respond_to do |format|
      format.turbo_stream do
        render turbo_stream: update_action_follow
      end
    end
  end


  private
  def update_action_follow
    private_target = "#{dom_id_for_follower(@user)} follow_user"
    turbo_stream.replace(private_target,
                         partial: 'profile/follow_button',
                         locals: {
                           user: @user
                         })
  end

  def update_count_follower
    private_target = "#{@user.id}-follower-count"
    turbo_stream.update(private_target,
                        partial: 'profile/follower_count',
                        locals: { user: @user
                        })
  end

预期响应格式应为TURBO_STREAM,但日志显示实际为HTML格式,进而出现报错,请问该如何解决?


解决方案

1. 让请求正确携带Turbo Stream标识

Hotwire Turbo需要请求携带text/vnd.turbo-stream.html的Accept头,才能触发控制器的format.turbo_stream分支。需要修改link_to,显式指定请求格式为turbo_stream,并确保Turbo处理该请求:

<%= turbo_frame_tag "#{dom_id(@user)} follow_user" do %>
  <% if following?(user) %>
    <%= link_to "Unfollow", profile_unfollow_path(id: user.id, format: :turbo_stream), method: :delete, class: "", data: { turbo: true } %>
  <% else %>
    <%= link_to "Follow", profile_follow_path(id: user.id, format: :turbo_stream), method: :post, class: "", data: { turbo: true } %>
  <% end %>
<% end %>

2. 修正DOM ID匹配问题

控制器中update_action_follow方法里的目标ID,必须和视图中turbo_frame_tag的ID完全一致。当前代码使用dom_id_for_follower(@user),如果这个方法的逻辑和dom_id(@user)不同,就会导致无法找到目标元素。直接替换为视图中一致的写法:

def update_action_follow
  private_target = "#{dom_id(@user)} follow_user"
  turbo_stream.replace(private_target,
                       partial: 'profile/follow_button',
                       locals: {
                         user: @user
                       })
end

3. 确保控制器正确赋值并处理响应

在follow和unfollow方法中,必须确保@user被正确赋值,否则视图局部渲染会出错。同时添加HTML格式的 fallback,避免请求异常:

def follow
  @user = User.find(params[:id])
  Relationship.create_or_find_by(follower_id: current_user.id, followee_id: @user.id)
  respond_to do |format|
    format.turbo_stream { render turbo_stream: update_action_follow }
    format.html { redirect_back fallback_location: root_path }
  end
end

def unfollow
  @user = User.find(params[:id])
  current_user.followed_user.where(followee_id: @user.id).destroy_all
  respond_to do |format|
    format.turbo_stream { render turbo_stream: update_action_follow }
    format.html { redirect_back fallback_location: root_path }
  end
end

4. 检查Turbo的引入状态

确认应用已正确加载Turbo:

  • 检查application.js中是否包含import "@hotwired/turbo-rails"
  • 确保布局文件里添加了<%= turbo_include_tags %>(Rails 7+)或其他正确加载Turbo JS的方式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 16:57:32