Rails 7 Turbo Stream无法传递current_user问题求助
Rails Turbo 流式消息删除按钮不显示问题
问题现象
系统中每个Applicant关联多条Message,双方用户可通过Applicant互发消息,消息流基础功能正常。但仅消息发布者可删除消息的逻辑存在异常:页面初始加载或刷新时删除按钮显示正常,通过Turbo流式加载的新消息却不显示删除按钮。
核心问题分析
- Turbo流渲染时无法自动继承页面的
@is_owner实例变量,而消息Partial依赖该变量判断是否显示删除按钮。 - 同时使用了两种Turbo广播逻辑(控制器手动渲染+模型
after_save_commit广播),导致逻辑冲突,且模型广播在后台Job执行,无法访问请求上下文(如current_user)。
解决方案
1. 移除重复的模型端广播逻辑
删除模型中与控制器重复的Turbo广播代码,避免逻辑冲突:
# app/models/message.rb class Message < ApplicationRecord # 移除该行重复广播逻辑 # after_save_commit -> { broadcast_append_later_to "applicant_messages_#{self.applicant_id}", partial: "messages/message", locals: { message: self }, target: "messages" } after_destroy_commit -> { broadcast_remove_to "applicant_messages_#{self.applicant_id}", target: "message_#{self.id}" } end
2. 在控制器Turbo流渲染中传递身份上下文
修改MessageController#create,计算当前用户的is_owner身份并显式传递给Partial:
# app/controllers/message_controller.rb class MessageController < ApplicationController before_action :authenticate_user! def create @message = Message.new(message_params) applicant = @message.applicant # 计算当前用户是否为项目所有者 @is_owner = current_user == applicant.project.user respond_to do |format| if @message.save format.turbo_stream do render turbo_stream: turbo_stream.append( "messages", # 对应页面中<div id="messages">的target ID partial: "messages/message", locals: { message: @message, is_owner: @is_owner } # 传递身份变量到Partial ), notice: 'Message was successfully created.' end format.json { render :show, status: :created, message: @message } else format.html { render :new, status: :unprocessable_entity } format.json { render json: @message.errors, status: :unprocessable_entity } end end end end
3. 修改Partial使用传入的局部变量
将Partial中依赖的@is_owner实例变量改为传入的is_owner局部变量:
# app/views/messages/_message.html.erb <%= turbo_frame_tag dom_id(message) do %> <p> <%= message.is_owner == true ? "#{message.applicant.project.user.first_name}" : "#{message.applicant.user.first_name}" %> (<%= message.id %>): <%= message.body %> <%# 使用传入的is_owner变量判断是否显示删除按钮 %> <% if message.is_owner == is_owner %> [<%= link_to "delete", message_delete_path(message.hashid), method: :delete, data: {turbo_method: :delete} %>] <% end %> </p> <% end %>
4. 统一初始渲染的变量传递
修改show.html.erb中初始渲染消息列表的代码,确保传递is_owner变量:
# app/views/applicants/show.html.erb <div class="container"> <div> <%= turbo_stream_from "applicant_messages_#{@applicant.id}" %> <div id="messages"> <%# 渲染消息列表时传递is_owner %> <%= render @messages, is_owner: @is_owner %> </div> </div> </div> <!-- 表单部分保持不变 --> <div class="container"> <%= form_for @message, url: message_create_path(@applicant.hashid),data: { controller: "message", action: "turbo:submit-end->message#reset"}, method: :post, html: {id: "message_form"}, remote: true do |f| %> <%= f.hidden_field :is_owner, value: @is_owner %> <%= f.hidden_field :applicant_id, value: @applicant.id %> <%= f.text_field :body, autofocus: true, autocomplete: 'off', placeholder: "Enter message", id: "message_body", class: "form-control", data: { turbo_stream: true } %> <%= f.submit 'Post message', class: 'btn btn-primary d-inline', data: {disable_with: "Working on it..."} %> <% end %> </div>
内容的提问来源于stack exchange,提问作者Frub
相关产品推荐
相关产品推荐

