我正在尝试学习带有轨道的涡轮增压,但遇到了一个我似乎无法解决的问题。我有一个结构,每个申请人都有消息。两个用户可以通过申请人互相发送消息。该流现在可以运行。
但是,我尝试将删除限制为仅发布该消息的用户。这在最初加载消息或刷新页面时起作用。但当消息流式传输时,删除选项不会出现。
它似乎无法识别流上的 current_user (设备)。我尝试将 current_user 添加为控制器和视图中的本地用户,但这不起作用。我看不到在模型中添加 current_user 的方法。
我想,问题之一是我觉得我的消息创建方法和保存方法后的广播正在做同样的事情。
任何人都可以确定我可以将 current_user 传递到 Turbo 流中以便出现删除按钮吗?如果做不到这一点,我的方法中的任何问题也将帮助我追踪问题
这是申请人控制器中的显示操作(页面最初加载时运行的操作):
class ApplicantController < ApplicationController
before_action :authenticate_user!
def show
@applicant = Applicant.find_by_hashid(params[:hashid])
max_messages = 200
@messages = @applicant.messages.order(created_at: :asc).last(max_messages)
current_user == @applicant.project.user ? @is_owner = true : @is_owner = false
@message = Message.new
respond_to do |format|
format.html
format.turbo_stream
end
end
end
这是消息控制器中的创建操作(创建新消息时运行的操作):
class MessageController < ApplicationController
before_action :authenticate_user!
def create
@message = Message.new(message_params)
respond_to do |format|
if @message.save
format.turbo_stream { render turbo_stream: turbo_stream.append("applicant_messages_#{@message.applicant_id}", partial: "messages/message", locals: { message: @message }), notice: 'Message was successfully created.' }
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
这是消息模型:
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
这是显示消息的 show.html.erb:
<div class="container">
<div>
<%= turbo_stream_from "applicant_messages_#{@applicant.id}" %>
<div id="messages">
<%= render @messages %>
</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..."} %>
</div>
这是 _messages.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 %>
<% if message.is_owner == @is_owner %>
[<%= link_to "delete", message_delete_path(message.hashid), method: :delete, data: {turbo_method: :delete} %>]
<% end %>
</p>
<% end %>
我建议将 user 作为局部变量传递给局部变量,并在内部检查它。另外,对于广播,仅使用控制器,不要使用回调进行广播(这是某种反模式)
这只是想法,您可以改进它并应用到您的代码中
在消息控制器的创建操作中:
if @message.save
@message.broadcast_append_to(
"applicant_messages_#{@message.applicant_id}",
partial: "messages/message",
target: "messages",
locals: { message: @message, user: current_user }
)
end
在
app/views/messages/_message.html.erb
部分:
<% if message.user_id == user.id %>
<%= render something.that.can.see.only.message.owner %>
<% else %>
<%= render something.that.see.others %>
<% end %>
当然,在这种情况下,您需要将
current_user
作为本地 user
传递到 app/views/applicants/show.html.erb
的消息容器中
<div id="messages">
<%= render @messages, user: current_user %>
</div>